from __future__ import annotations

import json
from datetime import date, datetime, timedelta
from typing import Any, Dict, List, Optional

from store_customer_lib.common import parse_fields_json, validate_birthday_month
from store_customer_lib.import_export.exporter import preview_markdown
from store_customer_lib.import_export.normalizer import clean_text, normalize_date


DUE_KEYWORDS = ("到期", "续费", "回访", "预约")


def apply_dynamic_filters(rows: List[dict], filters: Any) -> List[dict]:
    if not filters:
        return rows
    items = filters if isinstance(filters, list) else [filters]
    out = []
    for row in rows:
        fields = parse_fields_json(row.get("fields_json") or "{}")
        ok = True
        for item in items:
            fk = item.get("field_key") or item.get("field")
            op = item.get("op", "contains")
            expected = clean_text(item.get("value"))
            actual = clean_text(str(fields.get(fk, "")))
            if op == "eq" and actual != expected:
                ok = False
            elif op == "contains" and expected not in actual:
                ok = False
        if ok:
            out.append(row)
    return out


def _due_items_for_member(row: dict, within_days: int) -> List[Dict[str, str]]:
    today = date.today()
    end = today + timedelta(days=within_days)
    items: List[Dict[str, str]] = []

    def check(label: str, raw: str) -> None:
        nd = normalize_date(raw)
        if not nd:
            return
        try:
            d = date.fromisoformat(nd[:10])
        except ValueError:
            return
        if today <= d <= end:
            items.append({"label": label, "date": nd, "value": raw})

    if row.get("birthday"):
        check("生日", row["birthday"])
    if row.get("due_date"):
        check("到期日", row["due_date"])
    for fk, val in parse_fields_json(row.get("fields_json") or "{}").items():
        label = fk
        if any(k in str(fk) for k in DUE_KEYWORDS) or any(k in str(val) for k in DUE_KEYWORDS):
            check(label, str(val))
    return items


def apply_due_within_days_filter(rows: List[dict], within_days: int) -> List[dict]:
    out = []
    for row in rows:
        if _due_items_for_member(row, within_days):
            row = dict(row)
            row["due_items"] = _due_items_for_member(row, within_days)
            out.append(row)
    return out


def query_birthdays(conn, month: int, limit: int, with_extras: Any) -> Dict[str, Any]:
    mm = validate_birthday_month(str(month))
    if not mm:
        raise ValueError("invalid month")
    rows = [
        dict(r)
        for r in conn.execute(
            """SELECT * FROM store_members WHERE status='active'
               AND birthday IS NOT NULL AND birthday != '' AND substr(birthday, 6, 2)=?
               ORDER BY birthday LIMIT ?""",
            (mm, limit),
        )
    ]
    from store_customer_lib.common import attach_member_extras

    attach_member_extras(conn, rows, with_extras)
    labels = {
        r["field_key"]: r["label"]
        for r in conn.execute(
            "SELECT field_key, label FROM store_custom_field_defs WHERE entity='member'"
        )
    }
    return {
        "members": rows,
        "count": len(rows),
        "month": int(mm),
        "markdown": preview_markdown(rows, labels, limit=limit),
    }


def query_due(conn, within_days: int, limit: int, with_extras: Any) -> Dict[str, Any]:
    rows = [dict(r) for r in conn.execute("SELECT * FROM store_members WHERE status='active'")]
    matched = apply_due_within_days_filter(rows, within_days)[:limit]
    from store_customer_lib.common import attach_member_extras

    attach_member_extras(conn, matched, with_extras)
    labels = {
        r["field_key"]: r["label"]
        for r in conn.execute(
            "SELECT field_key, label FROM store_custom_field_defs WHERE entity='member'"
        )
    }
    return {
        "members": matched,
        "count": len(matched),
        "within_days": within_days,
        "markdown": preview_markdown(matched, labels, limit=limit),
    }
