"""Gemini Flash Lite page analysis with input-digest caching."""

from __future__ import annotations

import hashlib
import json
import logging
import os
import time
from typing import Any

log = logging.getLogger("crawler.gemini")

GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")
GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-flash-lite-latest")
GEMINI_TIMEOUT = float(os.getenv("GEMINI_ANALYSIS_TIMEOUT_SECONDS", "30"))
GEMINI_MAX_CHARS = int(os.getenv("GEMINI_MAX_INPUT_CHARS", "60000"))
GEMINI_ENABLED = os.getenv("GEMINI_ANALYSIS_ENABLED", "true").lower() in {"1", "true", "yes"}

_gemini_client = None

try:
    from google import genai
    if GEMINI_API_KEY:
        _gemini_client = genai.Client(api_key=GEMINI_API_KEY)
except Exception:
    genai = None


def _input_digest(text: str) -> str:
    return hashlib.sha256(text.encode()).hexdigest()[:32]


def _call_gemini(prompt: str, response_schema: dict | None = None) -> dict | None:
    if not _gemini_client:
        return None
    try:
        config = {}
        if response_schema:
            config["response_mime_type"] = "application/json"
            config["response_schema"] = response_schema
        response = _gemini_client.models.generate_content(
            model=GEMINI_MODEL,
            contents=prompt,
            config=config,
        )
        text = response.text or ""
        if response_schema:
            return json.loads(text)
        try:
            return json.loads(text)
        except json.JSONDecodeError:
            return {"raw_response": text}
    except Exception as exc:
        log.warning("Gemini call failed: %s", exc)
        return None


_PAGE_CLASS_SCHEMA = {
    "type": "OBJECT",
    "properties": {
        "page_class": {"type": "STRING"},
        "product": {"type": "BOOLEAN"},
        "has_product_catalogue": {"type": "BOOLEAN"},
        "product_page_role": {"type": "STRING"},
        "context_type": {"type": "STRING", "nullable": True},
        "context_label": {"type": "STRING", "nullable": True},
        "product_name": {"type": "STRING", "nullable": True},
        "product_family": {"type": "STRING", "nullable": True},
        "detected_sections": {"type": "ARRAY", "items": {"type": "STRING"}},
        "confidence": {"type": "NUMBER"},
        "reason": {"type": "STRING"},
    },
    "required": ["page_class", "product", "has_product_catalogue", "product_page_role", "confidence"],
}

_PAGE_CLASS_PROMPT = """You analyze a webpage to determine its page class. Return only compact JSON.

URL: {url}
Title: {title}

Visible text:
{text}

Links found on page:
{links}

Page classes to choose from:
- normal_page: A regular content page with no product configuration or catalogue
- catalogue_context_page: A category/application page listing multiple products (e.g. "Sports hall", "Downlights")
- product_listing_page: A page showing a list of products with filters
- product_family_page: A single product page with variants/options (e.g. "UNICO Q9 basic recessed")
- product_detail_page: A page showing detailed specs of one product
- product_configurator_entry: A live configurator where options change article numbers/prices
- product_configurator_state: A specific state inside a configurator
- product_modal: A popup overlay showing product information

Important: catalogue/context pages listing products are NOT products themselves.
Only detail/family/configurator pages should be marked as product=true."""


def analyze_page(
    url: str = "",
    title: str = "",
    visible_text: str = "",
    links: list[dict[str, str]] | None = None,
    headings: list[str] | None = None,
    force: bool = False,
) -> dict | None:
    if not _gemini_client or not GEMINI_ENABLED:
        return None
    if not force and len(visible_text) < 100:
        return None

    truncated = visible_text[:GEMINI_MAX_CHARS]
    digest = _input_digest(truncated)

    # Check DB cache
    try:
        from crawl_db import _connect
        conn = _connect()
        with conn.cursor() as cur:
            cur.execute(
                "SELECT output_json FROM ai_page_analysis WHERE input_digest = %s",
                (digest,),
            )
            row = cur.fetchone()
            if row and row[0]:
                cached = json.loads(row[0]) if isinstance(row[0], str) else row[0]
                log.info("Gemini cache hit for %s", url[:80])
                return cached
    except Exception:
        pass

    link_text = ", ".join(
        l.get("text", "") for l in (links or [])[:30] if l.get("text")
    )[:2000]

    prompt = _PAGE_CLASS_PROMPT.format(
        url=url,
        title=title,
        text=truncated,
        links=link_text if link_text else "none",
    )

    result = _call_gemini(prompt, response_schema=_PAGE_CLASS_SCHEMA)
    if result:
        result["classified_by"] = "gemini"
        result["input_digest"] = digest

        # Store in cache
        try:
            from crawl_db import _connect, _ensure_schema
            _ensure_schema()
            page_key = f"gemini:{digest}"
            conn = _connect()
            with conn.cursor() as cur:
                cur.execute(
                    "INSERT INTO ai_page_analysis (analysis_key, page_key, model, input_digest, output_json, confidence) "
                    "VALUES (%s,%s,%s,%s,%s,%s) "
                    "ON DUPLICATE KEY UPDATE output_json=VALUES(output_json), confidence=VALUES(confidence)",
                    (f"analysis:{digest}", page_key, GEMINI_MODEL, digest,
                     json.dumps(result, ensure_ascii=False),
                     result.get("confidence", 0.5)),
                )
            conn.commit()
        except Exception as exc:
            log.debug("Gemini cache save failed: %s", exc)

    return result
