"""Brand extraction from URL - the magic one-liner.

Usage:
    from tokenmoulds import brand_from_url

    brand = brand_from_url("https://acme.com")
    brand.save("acme-templates/")

    # Or individual formats:
    brand.save_word("acme.dotx")
    brand.save_powerpoint("acme.potx")
    brand.save_excel("acme.xltx")
    brand.save_tokens("acme.tokens.json")
"""

from __future__ import annotations

import urllib.request

from tokenmoulds.brand_from_url_css import (
    detect_locale,
    extract_brand_from_raw_css,
    extract_fonts_from_css,
    extract_inline_css,
    extract_site_name,
    find_css_urls,
    infer_brand_tone,
    infer_type_scale,
    normalize_font_name,
    select_fonts,
    select_primary_color,
    select_secondary_color,
)
from tokenmoulds.brand_from_url_models import BrandTemplates, ExtractedBrand
from tokenmoulds.css_to_dtcg import (
    extract_colors,
    extract_typography,
    is_color,
    normalize_color,
    parse_css,
)
from tokenmoulds.dtcg.emitter import emit_tokens_to_string
from tokenmoulds.dtcg.recipe import RecipeInputs, build_recipe


def fetch_url(url: str, timeout: int = 30) -> str:
    """Fetch URL content."""
    req = urllib.request.Request(
        url, headers={"User-Agent": "TokenMoulds/1.0 (Brand Extractor)"}
    )
    with urllib.request.urlopen(req, timeout=timeout) as response:
        return response.read().decode("utf-8", errors="ignore")


def extract_brand(url: str) -> ExtractedBrand:
    """Extract brand values from a URL.

    Args:
        url: Website URL to analyze

    Returns:
        ExtractedBrand with extracted values
    """
    html = fetch_url(url)

    # Collect all CSS (inline styles + external stylesheets)
    all_css = extract_inline_css(html)

    css_urls = find_css_urls(html, url)
    for css_url in css_urls[:5]:  # Limit to first 5 CSS files
        try:
            css_content = fetch_url(css_url)
            all_css += "\n" + css_content
        except Exception:
            pass

    # Include HTML itself for inline styles and CSS variables in attributes.
    all_content = html + "\n" + all_css

    # Prefer raw CSS heuristic extraction and fall back to tokenized parsing.
    raw_brand = extract_brand_from_raw_css(all_content)

    variables, rules = parse_css(all_css)
    colors = extract_colors(rules, variables)
    typography = extract_typography(rules)

    primary = raw_brand["primary"] or select_primary_color(colors)
    secondary = raw_brand["secondary"] or select_secondary_color(colors, primary)

    heading_font, body_font = select_fonts(typography)
    if raw_brand["heading_font"]:
        heading_font = raw_brand["heading_font"]
    if raw_brand["body_font"]:
        body_font = raw_brand["body_font"]

    name = extract_site_name(html, url)
    locale = detect_locale(html, url)
    tone = infer_brand_tone(all_css, colors)
    scale = infer_type_scale(typography)

    text_color = raw_brand["text_color"] or "#2B2B2B"
    if not raw_brand["text_color"]:
        for var in variables:
            if "ink" in var.name.lower() or "text" in var.name.lower():
                if is_color(var.value):
                    text_color = normalize_color(var.value)
                    break

    all_fonts_raw = extract_fonts_from_css(all_content)
    all_fonts: list[str] = []
    for font in all_fonts_raw:
        normalized = normalize_font_name(font)
        if normalized and normalized not in all_fonts:
            all_fonts.append(normalized)

    return ExtractedBrand(
        url=url,
        name=name,
        primary_color=primary,
        secondary_color=secondary,
        text_color=text_color,
        heading_font=heading_font,
        body_font=body_font,
        all_colors=colors,
        all_fonts=all_fonts,
        locale=locale,
        brand_tone=tone,
        type_scale_ratio=scale,
    )


def brand_from_url(url: str) -> BrandTemplates:
    """Extract brand from URL and generate templates."""
    brand = extract_brand(url)

    inputs = RecipeInputs(
        primary_color=brand.primary_color,
        secondary_color=brand.secondary_color,
        font_sans=brand.body_font,
        font_serif=brand.heading_font,
        baseline_pt=11.0,
        type_scale_ratio=brand.type_scale_ratio,
        brand_tone=brand.brand_tone,
        locale=brand.locale,
    )

    recipe = build_recipe(inputs)
    tokens_json = emit_tokens_to_string(recipe)

    return BrandTemplates(
        brand=brand,
        recipe_inputs=inputs,
        tokens_json=tokens_json,
    )


if __name__ == "__main__":
    import sys

    if len(sys.argv) < 2:
        print("Usage: python -m tokenmoulds.brand_from_url <url> [output_dir]")
        sys.exit(1)

    target_url = sys.argv[1]
    output_dir = sys.argv[2] if len(sys.argv) > 2 else "brand-output"

    print(f"Extracting brand from {target_url}...")
    brand = brand_from_url(target_url)

    print(f"\nBrand: {brand.brand.name}")
    print(f"Primary: {brand.brand.primary_color}")
    print(f"Secondary: {brand.brand.secondary_color}")
    print(f"Fonts: {brand.brand.heading_font} / {brand.brand.body_font}")
    print(f"Locale: {brand.brand.locale}")

    print(f"\nSaving to {output_dir}/...")
    saved = brand.save(output_dir)

    for fmt, path in saved.items():
        print(f"  {fmt}: {path}")
