"""Read a tenant's BrandForge analysis and reduce it to what an email needs.

BrandForge already crawls each tenant's site and extracts their real brand:
name, colour palette with roles, fonts, logos and page links. That is a far
better source for branding an email than the Organisation signup record, where
the trading name is often a placeholder.

The raw analysis is large and noisy, so this module picks only what a designer
would actually use, and applies email-specific rules the analysis does not know
about (SVG logos do not render in Gmail or Outlook; webp is unreliable).
"""
import json
import logging

from psycopg2 import sql

from app.services.infra.database import get_db_connection

logger = logging.getLogger(__name__)

# Gmail and Outlook do not render SVG, and webp support is patchy.
EMAIL_SAFE_IMAGE = (".png", ".jpg", ".jpeg", ".gif")

# Near-black/near-white are structural, not brand identity -- a "primary" of
# #000000 would produce the same generic email for every tenant.
_NEUTRAL = {"#000", "#000000", "#fff", "#ffffff"}


def _load_analysis(tenant_id: str):
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT EXISTS (SELECT FROM information_schema.tables "
                "WHERE table_schema = %s AND table_name = 'brandforge_analyses')",
                (tenant_id,),
            )
            if not cur.fetchone()[0]:
                return None
            cur.execute(
                sql.SQL("SELECT full_result FROM {}.brandforge_analyses "
                        "ORDER BY created_at DESC LIMIT 1").format(sql.Identifier(tenant_id))
            )
            row = cur.fetchone()
            if not row or not row[0]:
                return None
            result = row[0]
            return json.loads(result) if isinstance(result, str) else result
    except Exception as ex:
        logger.error(f"Could not read BrandForge analysis for {tenant_id}: {ex}")
        return None
    finally:
        conn.close()


def _pick_colors(analysis: dict) -> dict:
    """Primary and accent colours, skipping black/white which carry no identity."""
    palette = ((analysis.get("colors") or {}).get("palette")) or []
    branded = [c for c in palette
               if (c.get("hex") or "").lower() not in _NEUTRAL and c.get("hex")]
    branded.sort(key=lambda c: (c.get("confidence") or 0) * (c.get("score") or 1), reverse=True)

    primary = next((c["hex"] for c in branded if c.get("role") == "primary"), None)
    accent = next((c["hex"] for c in branded if c.get("role") == "accent"
                   and c["hex"] != primary), None)
    if not primary and branded:
        primary = branded[0]["hex"]
    if not accent:
        accent = next((c["hex"] for c in branded if c["hex"] != primary), None)
    return {"primary": primary, "accent": accent,
            "all": [c["hex"] for c in branded[:5]]}


def _pick_logo(analysis: dict) -> str:
    """An email-renderable logo, preferring a real header logo over a favicon."""
    assets = analysis.get("assets") or {}
    candidates = []
    for c in assets.get("logo_candidates") or []:
        if c.get("url"):
            candidates.append((c.get("is_header") is True, c["url"]))
    for url in (assets.get("homepage_logo_images") or []) + (assets.get("logo_images") or []):
        candidates.append((False, url))
    for url in assets.get("favicons") or []:
        candidates.append((False, url))

    # Header logos first, then anything else -- but only email-safe formats.
    for header_first in (True, False):
        for is_header, url in candidates:
            if is_header is header_first and url.lower().endswith(EMAIL_SAFE_IMAGE):
                return url
    return ""


def _pick_fonts(analysis: dict) -> str:
    families = [f.get("family") for f in (analysis.get("fonts") or []) if f.get("family")]
    # Always end on a web-safe fallback: mail clients cannot load web fonts.
    safe = [f for f in families if f and not f.startswith("-")][:2]
    return ", ".join(f"'{f}'" for f in safe) + (", Arial, sans-serif" if safe else "Arial, sans-serif")


def brandforge_profile(tenant_id: str) -> dict:
    """Email-relevant brand facts, or {} when the tenant has no analysis."""
    if not tenant_id:
        return {}
    analysis = _load_analysis(tenant_id)
    if not analysis:
        return {}

    assets = analysis.get("assets") or {}
    brand = analysis.get("brand") or {}
    colors = _pick_colors(analysis)

    # Dedup while preserving order; the analysis repeats links.
    seen, links = set(), []
    for url in assets.get("links") or []:
        if url not in seen:
            seen.add(url)
            links.append(url)

    return {
        "name": (assets.get("brand_name") or brand.get("name") or "").strip(),
        "summary": (brand.get("summary") or "").strip(),
        "primary_color": colors["primary"],
        "accent_color": colors["accent"],
        "palette": colors["all"],
        "font_stack": _pick_fonts(analysis),
        "logo_url": _pick_logo(analysis),
        "links": links,
        "hero_images": [u for u in (assets.get("homepage_hero_images") or [])
                        if u.lower().endswith(EMAIL_SAFE_IMAGE)],
    }
