"""Klant 360° — geaggregeerde data uit NAS, CRM, retail, trends."""
from __future__ import annotations

from typing import Any

from app.db import fetch_all, fetch_one
from app.services import projects as projects_svc


def _serialize_row(row: dict | None) -> dict | None:
    if not row:
        return None
    out = dict(row)
    for k, v in list(out.items()):
        if hasattr(v, "isoformat"):
            out[k] = v.isoformat()
    return out


def _serialize_rows(rows: list) -> list[dict]:
    return [_serialize_row(r) for r in rows if r]


def get_client_360(client_id: int) -> dict[str, Any]:
    client = fetch_one("SELECT * FROM clients WHERE id = %s", (client_id,))
    if not client:
        return {"ok": False, "error": "Client not found"}

    projs = projects_svc.list_projects(client_id=client_id, limit=50)
    links = fetch_all(
        """
        SELECT dl.*, p.name AS project_name
        FROM document_links dl
        LEFT JOIN cockpit_projects p ON p.id = dl.project_id
        WHERE dl.client_id = %s
        ORDER BY dl.created_at DESC
        """,
        (client_id,),
    )
    paths = [l["storage_path"] for l in links if l.get("storage_path")]
    docs: list[dict] = []
    if paths:
        placeholders = ",".join(["%s"] * len(paths))
        docs = fetch_all(
            f"""
            SELECT filename, storage_path, doc_type, word_count, sentiment_label,
                   sentiment_compound, analyzed_at, user_labels
            FROM document_analytics
            WHERE storage_path IN ({placeholders})
               OR storage_path LIKE ANY (
                   SELECT dl.storage_path || '/%%' FROM document_links dl
                   WHERE dl.client_id = %s AND dl.is_folder = TRUE
               )
            ORDER BY analyzed_at DESC NULLS LAST
            LIMIT 80
            """,
            tuple(paths + [client_id]),
        )
    sentiment_rows = fetch_all(
        """
        SELECT sentiment_label, COUNT(*) AS n, AVG(sentiment_compound) AS avg_c
        FROM document_analytics da
        WHERE EXISTS (
            SELECT 1 FROM document_links dl
            WHERE dl.client_id = %s
              AND (da.storage_path = dl.storage_path
                   OR (dl.is_folder AND da.storage_path LIKE dl.storage_path || '/%%'))
        )
        GROUP BY sentiment_label
        """,
        (client_id,),
    )
    top_words = fetch_all(
        """
        SELECT dwc.lemma, SUM(dwc.count) AS total
        FROM document_word_counts dwc
        JOIN document_analytics da ON da.storage_path = dwc.storage_path
        WHERE EXISTS (
            SELECT 1 FROM document_links dl
            WHERE dl.client_id = %s
              AND (da.storage_path = dl.storage_path
                   OR (dl.is_folder AND da.storage_path LIKE dl.storage_path || '/%%'))
        )
          AND NOT dwc.is_stopword
        GROUP BY dwc.lemma
        ORDER BY total DESC
        LIMIT 25
        """,
        (client_id,),
    )
    deals = fetch_all(
        "SELECT id, title, value, stage, next_action, deadline FROM deals WHERE client_id = %s ORDER BY updated_at DESC LIMIT 15",
        (client_id,),
    )
    stores = fetch_all(
        """
        SELECT s.id, s.name, s.chain, s.city, s.partnership_status, s.halal_certified
        FROM client_supermarket_links l
        JOIN supermarkets s ON s.id = l.supermarket_id
        WHERE l.client_id = %s
        LIMIT 30
        """,
        (client_id,),
    )
    trends = fetch_all(
        """
        SELECT DATE_TRUNC('month', da.analyzed_at) AS month,
               COUNT(*) AS docs,
               AVG(da.sentiment_compound) AS avg_sentiment,
               SUM(da.word_count) AS words
        FROM document_analytics da
        WHERE da.analyzed_at IS NOT NULL
          AND EXISTS (
            SELECT 1 FROM document_links dl
            WHERE dl.client_id = %s
              AND (da.storage_path = dl.storage_path
                   OR (dl.is_folder AND da.storage_path LIKE dl.storage_path || '/%%'))
          )
        GROUP BY 1
        ORDER BY 1 DESC
        LIMIT 12
        """,
        (client_id,),
    )
    for t in trends:
        if hasattr(t.get("month"), "isoformat"):
            t["month"] = t["month"].isoformat()

    return {
        "ok": True,
        "client": _serialize_row(client),
        "projects": projs,
        "links": _serialize_rows(links),
        "documents": _serialize_rows(docs),
        "sentiment_breakdown": _serialize_rows(sentiment_rows),
        "top_words": _serialize_rows(top_words),
        "deals": _serialize_rows(deals),
        "stores": _serialize_rows(stores),
        "monthly_trends": trends,
        "stats": {
            "linked_paths": len(links),
            "documents": len(docs),
            "projects": len(projs),
            "stores": len(stores),
            "deals": len(deals),
        },
    }
