#!/usr/bin/env python3
"""End-to-end smoke for insurance-customer-policy.

Runs every CLI subcommand against an isolated SQLite (set via
``INSURANCE_CUSTOMER_DB_PATH``) and asserts the responses are well-formed.
"""
from __future__ import annotations

import json
import os
import subprocess
import sys
import tempfile
from pathlib import Path

HERE = Path(__file__).resolve().parent
PKG = HERE


def run(*args: str) -> dict:
    cmd = [sys.executable, "-m", "insurance_customer_cli", *args]
    env = {**os.environ, "PYTHONPATH": str(PKG), "PYTHONIOENCODING": "utf-8"}
    r = subprocess.run(cmd, env=env, capture_output=True, text=True,
                       encoding="utf-8", timeout=60)
    if r.returncode not in (0, 1):
        raise SystemExit(f"unexpected rc={r.returncode}\nstdout={r.stdout}\nstderr={r.stderr}")
    if not r.stdout.strip():
        raise SystemExit(f"empty stdout for {args}\nstderr={r.stderr}")
    return json.loads(r.stdout.strip())


def assert_ok(data: dict, *args: str) -> dict:
    if not data.get("ok"):
        raise SystemExit(f"expected ok=True, got {data} for args={args}")
    return data


def assert_err(data: dict, code: str, *args: str) -> None:
    if data.get("ok") or data.get("error") != code:
        raise SystemExit(f"expected error={code}, got {data} for args={args}")


def main() -> int:
    tmp = tempfile.mkdtemp(prefix="ins_cust_smoke_")
    os.environ["INSURANCE_CUSTOMER_DB_PATH"] = str(Path(tmp) / "customer.sqlite3")

    print("[1] customer-add")
    d = run("customer-add", "--name", "张先生", "--phone", "13800138000",
            "--age", "35", "--income", "300000",
            "--household", '{"spouse":true,"children":2}', "--birthday", "1989-05-09")
    cid = assert_ok(d)["id"]
    assert cid == "C001", f"expected C001 got {cid}"

    d = run("customer-add", "--name", "李女士", "--phone", "13900139000", "--age", "40")
    cid2 = assert_ok(d)["id"]
    assert cid2 == "C002"

    print("[2] customer-query (keyword)")
    d = assert_ok(run("customer-query", "--keyword", "张"))
    assert d["count"] == 1 and d["customers"][0]["id"] == "C001"

    print("[3] customer-query (id, with policy_count/last_followup_at)")
    d = assert_ok(run("customer-query", "--customer-id", "C001"))
    assert d["customers"][0]["policy_count"] == 0
    assert d["customers"][0]["last_followup_at"] is None

    print("[4] customer-update (set income + children)")
    assert_ok(run("customer-update", "--customer-id", "C001",
                  "--set", '{"income":350000,"children":3,"tags":["VIP"]}'))
    d = assert_ok(run("customer-query", "--customer-id", "C001"))
    cust = d["customers"][0]
    assert cust["income"] == 350000
    assert cust["household"].get("children") == 3
    assert cust["tags"] == ["VIP"]

    print("[5] customer-exists")
    assert assert_ok(run("customer-exists", "--customer-id", "C001"))["exists"] is True
    assert assert_ok(run("customer-exists", "--customer-id", "C999"))["exists"] is False

    print("[6] policy-add (with pay-period derivation)")
    d = assert_ok(run("policy-add", "--customer-id", "C001",
                      "--company", "A保险公司", "--product", "重疾险XX",
                      "--type", "重疾险", "--coverage", "500000", "--premium", "8000",
                      "--effective-date", "2023-01-01", "--pay-period", "20年"))
    pid = d["id"]
    assert pid == "P001"
    assert d["expire_date"] == "2043-01-01", d
    assert d["next_pay_date"] == "2024-01-01", d

    assert_ok(run("policy-add", "--customer-id", "C001",
                  "--company", "B保险公司", "--product", "百万医疗",
                  "--type", "医疗险", "--coverage", "1000000", "--premium", "500",
                  "--effective-date", "2023-06-01", "--pay-period", "1年"))

    print("[7] policy-add: customer not found")
    assert_err(run("policy-add", "--customer-id", "C999",
                   "--company", "X", "--product", "X", "--type", "重疾险",
                   "--coverage", "1", "--premium", "1",
                   "--effective-date", "2024-01-01"), "customer_not_found")

    print("[8] policy-query")
    d = assert_ok(run("policy-query", "--customer-id", "C001"))
    assert d["count"] == 2

    print("[9] policy-update + delete")
    assert_ok(run("policy-update", "--policy-id", "P001",
                  "--set", '{"coverage":600000,"notes":"加保后"}'))
    d = assert_ok(run("policy-query", "--policy-id", "P001"))
    assert d["policies"][0]["coverage"] == 600000

    print("[10] policy-count-by-customer")
    assert assert_ok(run("policy-count-by-customer", "--customer-id", "C001"))["count"] == 2

    print("[11] followup-add + query")
    assert_ok(run("followup-add", "--customer-id", "C001",
                  "--content", "聊了养老险，很感兴趣",
                  "--next-step", "下周三见面详聊", "--next-date", "2024-05-15"))
    assert_ok(run("followup-add", "--customer-id", "C002", "--content", "电话联系，下次再聊"))
    d = assert_ok(run("followup-query", "--customer-id", "C001"))
    assert d["count"] == 1

    print("[12] gap-analysis (single)")
    d = assert_ok(run("gap-analysis", "--customer-id", "C001"))
    res = d["result"]
    assert res["coverage"]["重疾险"] is True
    assert res["coverage"]["医疗险"] is True
    assert res["coverage"]["意外险"] is False
    assert "意外险" in res["gaps"]
    assert "教育金" in res["gaps"]
    assert res["has_children"] is True

    print("[13] gap-analysis (all + filter)")
    d = assert_ok(run("gap-analysis", "--all", "--gap-type", "重疾险"))
    cust_ids = [r["customer_id"] for r in d["results"]]
    assert "C002" in cust_ids and "C001" not in cust_ids

    print("[14] customer-segment")
    d = assert_ok(run("customer-segment"))
    assert d["summary"]["total"] == 2
    assert any(c["customer_id"] == "C001" for c in d["active"])

    print("[15] customer-delete (blocked by policies)")
    assert_err(run("customer-delete", "--customer-id", "C001", "--yes"), "has_policies")
    assert_ok(run("policy-delete", "--policy-id", "P001", "--yes"))
    assert_ok(run("policy-delete", "--policy-id", "P002", "--yes"))
    assert_err(run("customer-delete", "--customer-id", "C001"), "need_confirm")
    assert_ok(run("customer-delete", "--customer-id", "C001", "--yes"))

    print("[16] dashboard")
    d = assert_ok(run("dashboard", "--json"))
    assert d["customers_total"] == 1
    assert d["policies_total"] == 0

    print("[17] customer-field add/query")
    assert_ok(run("customer-field-add", "--name", "风险偏好", "--type", "text"))
    d = assert_ok(run("customer-field-query"))
    assert any(f["name"] == "风险偏好" for f in d["fields"])

    print("ALL OK")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
