import json
import re
from collections import Counter
from urllib.parse import urljoin

import httpx
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy import text

from .auth import require_token
from .db import get_db

# Storefront customizer — per-store theme + header menu + which elements appear on cards /
# product pages, in what order. Lets RecordGod dress ANY shop without touching code.
router = APIRouter(prefix="/layout", tags=["layout"])

DEFAULTS = {
    "theme": {"primary": "#ff5db1", "accent": "#46d18a", "bg": "#0c0c0e",
              "panel": "#141418", "text": "#f0f0f2", "font": "system-ui", "logo": "",
              "radius": 12, "cardCols": 4},
    "menu": [{"label": "Records", "href": "/records"}, {"label": "Wanted", "href": "/wantlist"}],
    "card": ["cover", "title", "artist", "price", "condition", "cart"],
    "product_page": ["cover", "title", "artist", "price", "condition", "genre",
                     "tracklist", "cart", "related"],
}
# Every element the editor can place, per surface.
PALETTE = {
    "card": ["cover", "title", "artist", "price", "condition", "cart", "genre",
             "format", "year", "stock_badge", "wishlist"],
    "product_page": ["cover", "gallery", "title", "artist", "label", "price", "condition",
                     "genre", "format", "year", "country", "tracklist", "cart", "wishlist",
                     "description", "related", "dealgod_value"],
}


class ConfigIn(BaseModel):
    config: dict


class UrlIn(BaseModel):
    url: str


@router.get("")
async def get_layout(ident=Depends(require_token), db=Depends(get_db)):
    row = (await db.execute(text("SELECT config FROM store_config WHERE store_id=:s"),
                            {"s": ident["store_id"]})).first()
    cfg = row[0] if row else None
    if isinstance(cfg, str):
        cfg = json.loads(cfg)
    return {"ok": True, "config": cfg or DEFAULTS, "defaults": DEFAULTS, "palette": PALETTE}


@router.post("")
async def save_layout(body: ConfigIn, ident=Depends(require_token), db=Depends(get_db)):
    await db.execute(text("""
        INSERT INTO store_config (store_id, config, updated_at)
        VALUES (:s, CAST(:c AS jsonb), now())
        ON CONFLICT (store_id) DO UPDATE SET config = EXCLUDED.config, updated_at = now()
    """), {"s": ident["store_id"], "c": json.dumps(body.config)})
    await db.commit()
    return {"ok": True}


@router.post("/import-brand")
async def import_brand(body: UrlIn, ident=Depends(require_token)):
    """Pull a store's brand from its website — theme colour, logo, font — the 'bam, adapt
    colourway' move (same spirit as DealGod store-intel). Lightweight HTTP scrape."""
    url = body.url.strip()
    if not url.startswith("http"):
        url = "https://" + url
    try:
        async with httpx.AsyncClient(timeout=15, follow_redirects=True,
                                     headers={"User-Agent": "RecordGod/0.1 brand-import"}) as c:
            html = (await c.get(url)).text
    except Exception as e:
        raise HTTPException(400, f"could not fetch {url}: {e}")

    def meta(prop):
        m = (re.search(rf'<meta[^>]+(?:name|property)=["\']{re.escape(prop)}["\'][^>]+content=["\']([^"\']+)', html, re.I)
             or re.search(rf'<meta[^>]+content=["\']([^"\']+)["\'][^>]+(?:name|property)=["\']{re.escape(prop)}["\']', html, re.I))
        return m.group(1) if m else None

    theme_color = meta("theme-color")
    logo = meta("og:image")
    if not logo:
        m = re.search(r'<link[^>]+rel=["\'][^"\']*icon[^"\']*["\'][^>]+href=["\']([^"\']+)', html, re.I)
        logo = m.group(1) if m else None
    if logo and not logo.startswith("http"):
        logo = urljoin(url, logo)

    counts = Counter(h.lower() for h in re.findall(r'#[0-9a-fA-F]{6}', html))
    common = [h for h, _ in counts.most_common(24) if h not in ('#ffffff', '#000000')][:6]

    gf = re.search(r'fonts\.googleapis\.com/css2?\?family=([A-Za-z0-9+]+)', html)
    if gf:
        font = gf.group(1).replace('+', ' ')
    else:
        fm = re.search(r'font-family:\s*["\']?([A-Za-z0-9 \-]+)', html, re.I)
        font = fm.group(1).strip() if fm else None

    return {"ok": True, "palette": {
        "primary": theme_color or (common[0] if common else "#ff5db1"),
        "colors": common, "logo": logo or "", "font": font or "system-ui",
    }}
