from __future__ import annotations

import json
from typing import Any

from .mappings import plate_order_related_field_definitions, plate_order_relation_control_map


def _json_loads_safe(value: str) -> Any:
    try:
        return json.loads(value)
    except Exception:
        return value


def normalize_mdy_value(value: Any) -> Any:
    """尽量把明道云返回的字符串 JSON 规范化为 Python 对象。

    常见情况：
    - Relation/Attachment 可能返回字符串形式的 "[]" / "[{...}]"
    - 空值经常是 "[]"（字符串）
    """

    if value is None:
        return None

    if isinstance(value, str):
        s = value.strip()
        if s == "[]":
            return []
        if (s.startswith("[") and s.endswith("]")) or (s.startswith("{") and s.endswith("}")):
            return _json_loads_safe(s)
        return value

    return value


def extract_relation_rowids(value: Any) -> list[str]:
    """从 Relation 字段的 value 中提取 rowid 列表。

    兼容形态：
    - list[dict]（常见：[{rowid,name,link}, ...]）
    - str（可能是 JSON 字符串数组，如 "[{...}]" 或 "[]"；也可能是逗号分割 rowId）
    - dict（单条）
    """

    value = normalize_mdy_value(value)

    if value is None:
        return []

    if isinstance(value, list):
        out: list[str] = []
        for item in value:
            if isinstance(item, dict):
                rid = item.get("rowid") or item.get("rowId")
                if rid:
                    out.append(str(rid))
            elif isinstance(item, str) and item.strip():
                out.append(item.strip())
        return out

    if isinstance(value, dict):
        rid = value.get("rowid") or value.get("rowId")
        return [str(rid)] if rid else []

    if isinstance(value, str):
        s = value.strip()
        if not s or s == "[]":
            return []
        # 兜底：逗号分割
        return [x for x in (p.strip() for p in s.split(",")) if x]

    return []


def extract_plate_order_related_rowids(plate_order_row: dict[str, Any]) -> dict[str, list[str]]:
    """从开版主表行记录中提取各关联表的 rowid 列表。

    返回：
    - {related_key: [rowid, ...], ...}
    """

    result: dict[str, list[str]] = {}
    for control_id, related_key in plate_order_relation_control_map.items():
        rowids = extract_relation_rowids(plate_order_row.get(control_id))
        if rowids:
            result[related_key] = rowids
    return result


def flatten_row_by_field_definitions(
    row: dict[str, Any],
    field_definitions: dict[str, dict[str, Any]],
    *,
    drop_types: set[str] | None = None,
    drop_names: set[str] | None = None,
    include_system_keys: bool = True,
) -> dict[str, Any]:
    """按字段定义把一条明道云 row 转成“可读 dict”。

    - key 使用字段中文名（若缺失则回退 controlId）
    - value 做一定的 JSON 字符串规范化
    - 默认包含系统字段：rowid/ctime/utime（若存在）
    """

    drop_types = drop_types or set()
    drop_names = drop_names or set()

    out: dict[str, Any] = {}

    if include_system_keys:
        for k in ("rowid", "ctime", "utime"):
            if k in row:
                out[k] = row.get(k)

    for field_id, meta in field_definitions.items():
        name = meta.get("name") or field_id
        ftype = meta.get("type")

        if ftype in drop_types:
            continue
        if name in drop_names:
            continue

        out[name] = normalize_mdy_value(row.get(field_id))

    return out


def flatten_plate_order_related_row(related_key: str, related_row: dict[str, Any]) -> dict[str, Any]:
    """将开版关联表的一条 row 扁平化为 dict（用于入库 staging.related）。

    - 自动删除回溯 Relation 字段（开版管理/开发管理等）
    - 保留 rowid/ctime/utime（若存在）
    - 额外写入 source 信息，便于排查
    """

    meta = plate_order_related_field_definitions.get(related_key) or {}
    wsid = meta.get("worksheet_id")
    cn_name = meta.get("name")
    fields = meta.get("fields") or {}

    flat = flatten_row_by_field_definitions(
        related_row,
        fields,
        drop_types={"Relation"},
        drop_names={"开版管理", "开发管理"},
        include_system_keys=True,
    )

    # 扁平化结构：[{key: val}, ...] 里的每个元素是一条记录
    flat["source"] = related_key
    if cn_name:
        flat["source_name"] = cn_name
    if wsid:
        flat["worksheet_id"] = wsid

    return flat
