from __future__ import annotations

import argparse
import csv
import sys
import time
from pathlib import Path

from store_db.csv_safe import csv_safe_row
from store_db.db import connect
from store_db.operation_log import log_read
from store_db.response import emit_error, emit_ok

from store_marketing_lib.campaign import build_campaign_suggest, build_dormant_wake
from store_marketing_lib.context import build_campaign_context
from store_marketing_lib.meta import segment_preset_key
from store_marketing_lib.segments import query_segment, run_segment

SKILL = "store-marketing"


def _resolve_preset(conn, args: argparse.Namespace) -> str:
    preset = segment_preset_key(conn, getattr(args, "preset", None))
    if preset not in ("A", "B"):
        emit_error("invalid_preset", {"preset": getattr(args, "preset", None), "allowed": ["A", "B"]})
    return preset


def cmd_segment_run(args: argparse.Namespace) -> int:
    t0 = time.perf_counter()
    conn = connect()
    preset = _resolve_preset(conn, args)
    try:
        result = run_segment(conn, preset)
    except ValueError as e:
        emit_error("invalid_preset", {"detail": str(e)})
    log_read(
        conn, args, skill=SKILL, command="segment-run", table_name="store_members",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    body = {
        "preset": result["preset"],
        "total": result["total"],
        "segments": result["segments"],
    }
    emit_ok(body)
    return 0


def cmd_campaign_suggest(args: argparse.Namespace) -> int:
    t0 = time.perf_counter()
    conn = connect()
    preset = _resolve_preset(conn, args)
    try:
        seg_result = run_segment(conn, preset)
    except ValueError:
        emit_error("invalid_preset")
    segment_name = args.segment or "沉睡"
    plan = build_campaign_suggest(
        conn,
        segment=segment_name,
        service=args.service,
        festival=args.festival,
        segment_data=seg_result["raw_segments"],
    )
    log_read(
        conn, args, skill=SKILL, command="campaign-suggest", table_name="store_members",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok(plan)
    return 0


def cmd_dormant_wake(args: argparse.Namespace) -> int:
    t0 = time.perf_counter()
    conn = connect()
    preset = _resolve_preset(conn, args)
    seg_result = run_segment(conn, preset)
    plan = build_dormant_wake(conn, seg_result["raw_segments"])
    log_read(
        conn, args, skill=SKILL, command="dormant-wake", table_name="store_members",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok(plan)
    return 0


def cmd_segment_query(args: argparse.Namespace) -> int:
    t0 = time.perf_counter()
    conn = connect()
    preset = _resolve_preset(conn, args)
    try:
        result = query_segment(conn, preset, args.name, limit=int(args.limit or 200))
    except ValueError as e:
        emit_error("invalid_segment", {"detail": str(e), "name": args.name, "preset": preset})
    log_read(
        conn, args, skill=SKILL, command="segment-query", table_name="store_members",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok(result)
    return 0


def cmd_campaign_context(args: argparse.Namespace) -> int:
    t0 = time.perf_counter()
    conn = connect()
    preset = _resolve_preset(conn, args)
    ctx = build_campaign_context(
        conn,
        preset=preset,
        segment=args.segment,
        service=args.service,
    )
    log_read(
        conn, args, skill=SKILL, command="campaign-context", table_name="store_members",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok(ctx)
    return 0


def cmd_segment_export(args: argparse.Namespace) -> int:
    t0 = time.perf_counter()
    conn = connect()
    preset = (args.preset or "A").upper()
    try:
        result = query_segment(conn, preset, args.name, limit=10000)
    except ValueError as e:
        emit_error("invalid_segment", {"detail": str(e)})
    path = Path(args.path)
    path.parent.mkdir(parents=True, exist_ok=True)
    fieldnames = ["member_id", "name", "phone", "last_visit_at", "balance"]
    with path.open("w", encoding="utf-8-sig", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")
        writer.writeheader()
        for m in result["members"]:
            mid = m.get("id") or m.get("member_id")
            row = conn.execute(
                """SELECT m.id AS member_id, m.name, m.phone, c.last_visit_at, w.balance
                   FROM store_members m
                   LEFT JOIN store_consumption_log c ON c.member_id=m.id
                   LEFT JOIN store_wallet w ON w.member_id=m.id WHERE m.id=?""",
                (mid,),
            ).fetchone()
            if row:
                writer.writerow(csv_safe_row(dict(row)))
    log_read(
        conn, args, skill=SKILL, command="segment-export", table_name="store_members",
        duration_ms=int((time.perf_counter() - t0) * 1000),
    )
    emit_ok({"path": str(path), "segment": args.name, "count": result["count"]})
    return 0


def build_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(description="Store marketing CLI")
    sub = p.add_subparsers(dest="cmd", required=True)

    s = sub.add_parser("segment-run")
    s.add_argument("--preset", choices=["A", "B", "a", "b"], help="默认读 store_meta.segment_preset")
    s.add_argument("--session-id")
    s.set_defaults(func=cmd_segment_run)

    s = sub.add_parser("campaign-suggest")
    s.add_argument("--segment", default="沉睡")
    s.add_argument("--service")
    s.add_argument("--festival")
    s.add_argument("--preset", choices=["A", "B", "a", "b"], help="默认读 store_meta.segment_preset")
    s.add_argument("--session-id")
    s.set_defaults(func=cmd_campaign_suggest)

    s = sub.add_parser("dormant-wake")
    s.add_argument("--preset", choices=["A", "B", "a", "b"], help="默认读 store_meta.segment_preset")
    s.add_argument("--session-id")
    s.set_defaults(func=cmd_dormant_wake)

    s = sub.add_parser("segment-query")
    s.add_argument("--preset", choices=["A", "B", "a", "b"], help="默认读 store_meta.segment_preset")
    s.add_argument("--name", required=True, help="分群名：高价值/高频/沉睡/新客/高净值/稳定复购")
    s.add_argument("--limit", type=int, default=200)
    s.add_argument("--session-id")
    s.set_defaults(func=cmd_segment_query)

    s = sub.add_parser("campaign-context")
    s.add_argument("--preset", choices=["A", "B", "a", "b"], help="默认读 store_meta.segment_preset")
    s.add_argument("--segment")
    s.add_argument("--service")
    s.add_argument("--session-id")
    s.set_defaults(func=cmd_campaign_context)

    s = sub.add_parser("segment-export")
    s.add_argument("--preset", choices=["A", "B", "a", "b"], help="默认读 store_meta.segment_preset")
    s.add_argument("--name", required=True)
    s.add_argument("--path", required=True)
    s.add_argument("--session-id")
    s.set_defaults(func=cmd_segment_export)

    return p


def main() -> int:
    args = build_parser().parse_args()
    return int(args.func(args))


if __name__ == "__main__":
    sys.exit(main())
