"""客户自定义字段白名单过滤服务"""
from __future__ import annotations

RESERVED_KEYS = frozenset({"password_hash", "wechat_avatar", "source", "cin7", "xero"})

PRESET_KEYS = frozenset({
    "company", "birthday", "gender",
    "vat_number", "bill_company", "bill_line1", "bill_line2",
    "bill_city", "bill_state", "bill_postal_code", "bill_country",
})

CUSTOM_KEYS = frozenset({f"custom_{i}" for i in range(1, 6)})

ALLOWED_KEYS = PRESET_KEYS | CUSTOM_KEYS

VALID_TYPES = {"text", "date", "select", "textarea"}
VALID_GROUPS = {"profile", "billing", "custom"}

_BILLING_KEYS = frozenset({
    "bill_company", "bill_line1", "bill_line2",
    "bill_city", "bill_state", "bill_postal_code", "bill_country",
})


def normalize_field(raw: dict, strict: bool = False) -> dict:
    """校验并规范化单个字段配置，strict=True 时抛出 ValueError。"""
    key = str(raw.get("key", "")).strip()
    if not key or key in RESERVED_KEYS:
        raise ValueError(f"Invalid field key: {key!r}")
    if key not in ALLOWED_KEYS:
        raise ValueError(f"Unknown field key (not in preset or custom_1~5): {key!r}")
    field_type = str(raw.get("type", "text")).strip()
    if field_type not in VALID_TYPES:
        raise ValueError(f"Invalid field type: {field_type!r}")
    group = str(raw.get("group", "profile")).strip()
    if group not in VALID_GROUPS:
        raise ValueError(f"Invalid field group: {group!r}")
    return {
        "key": key,
        "type": field_type,
        "group": group,
        "label_zh": str(raw.get("label_zh", key)).strip(),
        "label_en": str(raw.get("label_en", key)).strip(),
        "enabled": bool(raw.get("enabled", False)),
        "required": bool(raw.get("required", False)),
        "options": list(raw.get("options") or []),
    }


def normalize_fields(raw_list: list, strict: bool = False) -> list:
    """
    批量校验字段配置列表。
    strict=False（默认）：静默跳过无效项（读取路径）。
    strict=True：遇到第一个无效项即抛出 ValueError（Admin 保存路径 → 422）。
    返回去重后的列表（按 key 去重，保留第一个）。
    """
    seen: set[str] = set()
    result = []
    for item in (raw_list or []):
        try:
            f = normalize_field(item, strict=strict)
        except (ValueError, TypeError, AttributeError) as e:
            if strict:
                raise ValueError(str(e)) from e
            continue
        if f["key"] in seen:
            continue
        seen.add(f["key"])
        result.append(f)
    return result


def filter_profile_data(extra_data: dict, enabled_fields: list) -> dict:
    """从 extra_data 中只返回已启用字段的值，永远过滤掉保留键。"""
    allowed = {f["key"] for f in enabled_fields if f.get("enabled")}
    return {
        k: v
        for k, v in (extra_data or {}).items()
        if k in allowed and k not in RESERVED_KEYS
    }


def filter_input(raw: dict, enabled_fields: list) -> dict:
    """过滤客户提交的字段值，只保留已启用的、非保留的键。"""
    allowed = {f["key"] for f in enabled_fields if f.get("enabled")}
    return {
        k: v
        for k, v in (raw or {}).items()
        if k in allowed and k not in RESERVED_KEYS
    }


def validate_required(data: dict, enabled_fields: list) -> list[str]:
    """返回已启用且必填但缺失值的字段 key 列表。"""
    return [
        f["key"]
        for f in enabled_fields
        if f.get("enabled") and f.get("required") and not data.get(f["key"])
    ]


def build_customer_email_vars(extra_data: dict, enabled_fields: list) -> dict:
    """
    构建邮件模板变量，前缀 customer. 和 billing.。
    只包含已启用的字段（通过 filter_profile_data 过滤）。
    bill_* 键去掉 bill_ 前缀放入 billing. 命名空间。
    """
    filtered = filter_profile_data(extra_data, enabled_fields)
    vars_: dict = {}
    for k, v in filtered.items():
        if k in _BILLING_KEYS:
            billing_key = k[len("bill_"):]  # 去掉 "bill_" 前缀
            vars_[f"billing.{billing_key}"] = v or ""
        else:
            vars_[f"customer.{k}"] = v or ""
    return vars_
