"""Shared-db read helpers for insurance-product-analysis."""
from __future__ import annotations

import json
import sqlite3
from datetime import datetime, timedelta

from insurance_product_cli import db


def gap_analysis(customer_id: str | None = None, gap_type: str | None = None,
                 all_customers: bool = False) -> dict:
    conn = db.connect()
    try:
        need_types = ["重疾险", "医疗险", "意外险", "寿险", "养老险", "教育金"]
        if customer_id:
            row = conn.execute(
                "SELECT id, name FROM customers WHERE id=? AND status='active'",
                (customer_id,),
            ).fetchone()
            if not row:
                return {"ok": False, "error": "customer_not_found"}
            results = [row]
        elif all_customers or gap_type:
            results = list(
                conn.execute("SELECT id, name FROM customers WHERE status='active' ORDER BY id")
            )
        else:
            return {"ok": False, "error": "need_customer_id_or_all"}

        payload = []
        for r in results:
            owned = {
                row["product_type"]
                for row in conn.execute(
                    "SELECT DISTINCT product_type FROM policies WHERE customer_id=? AND status='active'",
                    (r["id"],),
                )
                if row["product_type"]
            }
            gaps = [t for t in need_types if t not in owned]
            item = {"customer_id": r["id"], "name": r["name"], "owned_types": sorted(owned), "gaps": gaps}
            if customer_id:
                return {"ok": True, "result": item}
            payload.append(item)
        if gap_type:
            payload = [x for x in payload if gap_type in x.get("gaps", [])]
        return {"ok": True, "results": payload, "count": len(payload)}
    finally:
        conn.close()


def customer_query(customer_id: str | None = None, keyword: str | None = None) -> dict:
    conn = db.connect()
    try:
        cur = conn.cursor()
        if customer_id:
            rows = list(cur.execute("SELECT * FROM customers WHERE id=? AND status='active'", (customer_id,)))
        elif keyword:
            kw = f"%{keyword}%"
            rows = list(
                cur.execute(
                    "SELECT * FROM customers WHERE status='active' AND (id LIKE ? OR name LIKE ? OR phone LIKE ?) "
                    "ORDER BY created_at DESC",
                    (kw, kw, kw),
                )
            )
        else:
            rows = list(cur.execute("SELECT * FROM customers WHERE status='active' ORDER BY created_at DESC"))
        customers: list[dict] = []
        for row in rows:
            d = dict(row)
            d["policies_count"] = int(
                conn.execute(
                    "SELECT COUNT(*) AS n FROM policies WHERE customer_id=? AND status='active'",
                    (row["id"],),
                ).fetchone()["n"]
            )
            last_fu = conn.execute(
                "SELECT MAX(created_at) AS ts FROM followups WHERE customer_id=?",
                (row["id"],),
            ).fetchone()["ts"]
            d["last_followup_at"] = last_fu
            for k in ("household_json", "tags_json", "fields_json"):
                try:
                    d[k[:-5]] = json.loads(d.get(k) or "{}")
                except json.JSONDecodeError:
                    d[k[:-5]] = {}
            customers.append(d)
        return {"ok": True, "customers": customers, "count": len(customers)}
    finally:
        conn.close()


def policy_query(customer_id: str | None = None, product_type: str | None = None) -> dict:
    conn = db.connect()
    try:
        cur = conn.cursor()
        if customer_id:
            rows = list(
                cur.execute(
                    "SELECT * FROM policies WHERE customer_id=? AND status='active' ORDER BY effective_date DESC",
                    (customer_id,),
                )
            )
        elif product_type:
            rows = list(
                cur.execute(
                    "SELECT * FROM policies WHERE product_type=? AND status='active' ORDER BY effective_date DESC",
                    (product_type,),
                )
            )
        else:
            rows = list(cur.execute("SELECT * FROM policies WHERE status='active' ORDER BY effective_date DESC"))
        return {"ok": True, "policies": [dict(r) for r in rows], "count": len(rows)}
    finally:
        conn.close()


def customer_segment() -> dict:
    conn = db.connect()
    try:
        now = datetime.now()
        d30 = (now - timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S")
        d60 = (now - timedelta(days=60)).strftime("%Y-%m-%d %H:%M:%S")
        rows = list(conn.execute("SELECT * FROM customers WHERE status='active' ORDER BY created_at DESC"))
        hi_value: list[dict] = []
        active: list[dict] = []
        new: list[dict] = []
        dormant: list[dict] = []
        for r in rows:
            cid = r["id"]
            premium = float(
                conn.execute(
                    "SELECT COALESCE(SUM(premium),0) AS s FROM policies WHERE customer_id=? AND status='active'",
                    (cid,),
                ).fetchone()["s"]
            )
            last_followup = conn.execute(
                "SELECT MAX(created_at) AS ts FROM followups WHERE customer_id=?",
                (cid,),
            ).fetchone()["ts"]
            slot = {"customer_id": cid, "name": r["name"]}
            if premium > 50000:
                hi_value.append(slot)
            if r["created_at"] and str(r["created_at"]) >= d30:
                new.append(slot)
            if last_followup:
                if str(last_followup) >= d30:
                    active.append(slot)
                elif str(last_followup) < d60:
                    dormant.append(slot)
            elif r["created_at"] and str(r["created_at"]) < d60:
                dormant.append(slot)
        return {
            "ok": True,
            "hi_value": hi_value,
            "active": active,
            "new": new,
            "dormant": dormant,
        }
    finally:
        conn.close()
