from __future__ import annotations

import json
import sqlite3
from datetime import datetime
from typing import Any, Dict, List, Optional

from store_db.ids import next_id

from store_customer_lib.import_export.exporter import preview_markdown
from store_customer_lib.import_export.mapper import row_to_member_payload
from store_customer_lib.import_export.normalizer import clean_text, is_blank, normalize_date
from store_customer_lib.import_export.parser import parse_file


def _upsert_member(conn: sqlite3.Connection, payload: Dict[str, Any]) -> str:
    phone = payload.get("phone") or ""
    existing = None
    if phone:
        existing = conn.execute(
            "SELECT id FROM store_members WHERE phone=? AND status='active'",
            (phone,),
        ).fetchone()
    if not existing and payload.get("name"):
        existing = conn.execute(
            "SELECT id FROM store_members WHERE name=? AND status='active' LIMIT 1",
            (payload["name"],),
        ).fetchone()
    mid = existing["id"] if existing else next_id(conn, "M", "store_members")
    tags_json = json.dumps(payload.get("tags") or [], ensure_ascii=False)
    fields_json = json.dumps(payload.get("fields") or {}, ensure_ascii=False)
    if existing:
        conn.execute(
            """UPDATE store_members SET phone=?, birthday=?, due_date=?, note=?,
               tags_json=?, fields_json=?, updated_at=datetime('now','localtime') WHERE id=?""",
            (
                phone,
                payload.get("birthday") or "",
                payload.get("due_date") or "",
                payload.get("note") or "",
                tags_json,
                fields_json,
                mid,
            ),
        )
    else:
        conn.execute(
            """INSERT INTO store_members (id, name, phone, birthday, due_date, note, tags_json, fields_json)
               VALUES (?,?,?,?,?,?,?,?)""",
            (
                mid,
                payload["name"],
                phone,
                payload.get("birthday") or "",
                payload.get("due_date") or "",
                payload.get("note") or "",
                tags_json,
                fields_json,
            ),
        )
        conn.execute("INSERT INTO store_wallet (member_id) VALUES (?)", (mid,))
        conn.execute(
            "INSERT INTO store_consumption_log (member_id, visit_count) VALUES (?,0) ON CONFLICT(member_id) DO NOTHING",
            (mid,),
        )
    return mid


def _add_followup(conn: sqlite3.Connection, member_id: str, content: str, contact_at: str) -> None:
    fid = next_id(conn, "F", "store_followups")
    nfd = (normalize_date(contact_at) or contact_at or datetime.now().strftime("%Y-%m-%d"))[:10]
    conn.execute(
        """INSERT INTO store_followups (id, member_id, content, contact_at, next_followup_date)
           VALUES (?,?,?,?,?)""",
        (fid, member_id, content, contact_at or nfd, nfd),
    )


def run_import(conn: sqlite3.Connection, file_path: str, commit: bool) -> Dict[str, Any]:
    parsed = parse_file(file_path)
    warnings: List[str] = []
    preview_rows: List[Dict[str, Any]] = []
    new_fields: List[str] = []
    customer_count = 0
    record_count = 0

    for table in parsed["tables"]:
        mode = table.get("mode", "generic")
        for row in table["rows"]:
            if mode == "grouped_records":
                name = None
                for label, val in row.items():
                    if not is_blank(val) and ("姓名" in label or label.endswith("_姓名")):
                        name = clean_text(val)
                        break
                if not name:
                    warnings.append("跳过分组行：缺少姓名")
                    continue
                payload = row_to_member_payload(conn, row)
                payload["name"] = name
                preview_rows.append({"name": name, "mode": "grouped"})
                customer_count += 1
                if commit:
                    mid = _upsert_member(conn, payload)
                    for label, val in row.items():
                        if is_blank(val):
                            continue
                        if "日期" in label or "记录" in label:
                            _add_followup(conn, mid, "{}: {}".format(label, val), val)
                            record_count += 1
            else:
                payload = row_to_member_payload(conn, row)
                if not payload.get("name"):
                    warnings.append("跳过一行：缺少姓名")
                    continue
                for fk in payload.get("fields", {}):
                    if fk not in new_fields:
                        new_fields.append(fk)
                preview_rows.append({"name": payload["name"], "fields": list(payload.get("fields", {}).keys())})
                customer_count += 1
                if commit:
                    _upsert_member(conn, payload)

    field_defs = [
        dict(r)
        for r in conn.execute(
            "SELECT field_key, label FROM store_custom_field_defs WHERE entity='member'"
        ).fetchall()
    ]
    labels = {d["field_key"]: d["label"] for d in field_defs}
    summary = {
        "mode": "commit" if commit else "preview",
        "source_file": file_path,
        "customer_count": customer_count,
        "record_count": record_count,
        "new_field_count": len(new_fields),
        "warnings": warnings,
        "preview_rows": preview_rows[:20],
    }
    summary["markdown"] = preview_markdown(
        [{"name": p.get("name"), "fields_json": "{}"} for p in preview_rows],
        labels,
        limit=20,
    )
    return summary
