#!/usr/bin/env python3
"""layout-spec: expand compact layout/typography shorthand to Tailwind classes."""

import json
import os
import re
import sys

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SKILL_DIR = os.path.dirname(SCRIPT_DIR)
CONFIG_PATH = os.path.join(SKILL_DIR, "config.json")
PROJECT_ROOT = os.path.abspath(os.path.join(SKILL_DIR, "..", "..", ".."))


def parse_tokens_css(tokens_file):
    with open(tokens_file, "r") as f:
        content = f.read()

    tokens = {"fontSizes": [], "colors": [], "spacing": []}

    theme_match = re.search(r"@theme\s*\{([^}]+)\}", content)
    if not theme_match:
        print("ERROR: No @theme block found in " + tokens_file, file=sys.stderr)
        sys.exit(1)

    for line in theme_match.group(1).split("\n"):
        line = line.strip()
        if not line or line.startswith("/*"):
            continue
        m = re.match(r"--([\w][\w-]*?):\s*", line)
        if not m:
            continue
        prop = m.group(1)

        if prop.startswith("text-") and not prop.endswith("--line-height"):
            tokens["fontSizes"].append(prop[5:])
        elif prop.startswith("color-"):
            tokens["colors"].append(prop[6:])
        elif prop.startswith("spacing-"):
            tokens["spacing"].append(prop[8:])

    return tokens


def bootstrap_config(tokens_file_rel="src/css/tokens.css"):
    tokens_file = os.path.join(PROJECT_ROOT, tokens_file_rel)
    if not os.path.isfile(tokens_file):
        print(f"ERROR: {tokens_file_rel} not found at {tokens_file}", file=sys.stderr)
        sys.exit(1)

    tokens = parse_tokens_css(tokens_file)

    config = {
        "fontWeightPrefix": "font-",
        "lineHeightMap": {
            "1": "leading-none",
            "1.1": "leading-tight",
            "1.2": "leading-snug",
            "1.4": "leading-normal",
            "1.5": "leading-relaxed",
            "1.6": "leading-loose",
        },
        "prefixes": {"fs": "text-", "fw": "font-", "lh": "leading-"},
        "passthrough": [
            "m", "mt", "mr", "mb", "ml", "mx", "my",
            "p", "pt", "pr", "pb", "pl", "px", "py",
            "gap", "gap-x", "gap-y",
            "text", "bg", "border",
        ],
        "breakpoints": ["sm", "md", "lg", "xl"],
        "tokensFile": tokens_file_rel,
        "discoveredTokens": tokens,
    }

    with open(CONFIG_PATH, "w") as f:
        json.dump(config, f, indent=2)
        f.write("\n")

    print(
        'Default config created at ".claude/skills/layout-spec/config.json". Edit to customize.',
        file=sys.stderr,
    )
    return config


def load_config():
    if not os.path.isfile(CONFIG_PATH):
        return bootstrap_config()
    with open(CONFIG_PATH, "r") as f:
        return json.load(f)


def expand_token(token, config):
    """Expand a single shorthand token. Returns (class, warning|None). Raises ValueError on hard error."""
    parts = token.split("-")
    if len(parts) < 2:
        raise ValueError(f"Invalid token '{token}' — must be <prefix>-<value>")

    prefixes = config["prefixes"]
    passthrough = config["passthrough"]
    breakpoints = config["breakpoints"]
    discovered = config.get("discoveredTokens", {})

    matched_prefix = None
    remaining = None

    if len(parts) >= 3:
        two_seg = f"{parts[0]}-{parts[1]}"
        if two_seg in passthrough or two_seg in prefixes:
            matched_prefix = two_seg
            remaining = parts[2:]

    if matched_prefix is None:
        if parts[0] in prefixes or parts[0] in passthrough:
            matched_prefix = parts[0]
            remaining = parts[1:]

    if matched_prefix is None:
        raise ValueError(
            f"Unknown prefix in '{token}'. Known: "
            + ", ".join(sorted(set(list(prefixes.keys()) + passthrough)))
        )

    if not remaining:
        raise ValueError(f"No value in '{token}'")

    bp = None
    if remaining[0] in breakpoints and len(remaining) >= 2:
        bp = remaining[0]
        value = "-".join(remaining[1:])
    else:
        value = "-".join(remaining)

    warning = None

    if matched_prefix in prefixes:
        if matched_prefix == "fs":
            if value not in discovered.get("fontSizes", []):
                avail = ", ".join(discovered.get("fontSizes", []))
                raise ValueError(f"Font size token 'text-{value}' not found in tokens.css. Available: {avail}")
            out = f"{prefixes['fs']}{value}"

        elif matched_prefix == "fw":
            out = f"{config.get('fontWeightPrefix', 'font-')}{value}"

        elif matched_prefix == "lh":
            lh_map = config.get("lineHeightMap", {})
            if value in lh_map:
                out = lh_map[value]
            else:
                out = f"leading-[{value}]"
                warning = f"No line-height mapping for '{value}', using arbitrary value leading-[{value}]"
        else:
            out = f"{prefixes[matched_prefix]}{value}"
    else:
        out = f"{matched_prefix}-{value}"

    if bp:
        out = f"{bp}:{out}"

    return out, warning


def expand_shorthand(input_str, config):
    """Expand comma-separated shorthand. Returns (string, [warnings]). Raises ValueError."""
    tokens = [t.strip() for t in input_str.split(",") if t.strip()]
    results = []
    warnings = []
    for t in tokens:
        cls, w = expand_token(t, config)
        results.append(cls)
        if w:
            warnings.append(w)
    return " ".join(results), warnings


def expand_inline(text, config):
    """Expand all ![...] markers in text. Returns (string, [warnings]). Raises ValueError."""
    warnings = []

    def repl(m):
        expanded, w = expand_shorthand(m.group(1), config)
        warnings.extend(w)
        return expanded

    return re.sub(r"!\[([^\]]+)\]", repl, text), warnings


def main():
    config = load_config()

    if len(sys.argv) < 2:
        raw = sys.stdin.read().strip()
    else:
        raw = " ".join(sys.argv[1:])

    if not raw:
        print("ERROR: No input provided", file=sys.stderr)
        sys.exit(1)

    try:
        if "![" in raw:
            result, warnings = expand_inline(raw, config)
        else:
            result, warnings = expand_shorthand(raw, config)
    except ValueError as e:
        print(f"ERROR: {e}", file=sys.stderr)
        sys.exit(1)

    for w in warnings:
        print(f"WARNING: {w}", file=sys.stderr)

    print(result)


if __name__ == "__main__":
    main()
