from __future__ import annotations

from typing import Any, Dict, List

from ...sync_system.resolve_ids import IDResolver
from ...validation import SchemaDiffValidator
from .compare_ops import build_data_id_normalization_map


def _compact_repr(value: Any, *, max_len: int = 80) -> str:
    text = repr(value)
    if len(text) <= max_len:
        return text
    return text[: max_len - 3] + "..."


def _append_post_check_error(node, message: str) -> None:
    if not message:
        return
    if node.error:
        if message not in node.error:
            node.error = f"{node.error} | {message}"
        return
    node.error = message


async def evaluate_consistency_for_node_type(
    *,
    node_type: str,
    strategy,
    local_collection,
    remote_collection,
    binding_manager,
    logger,
    depend_fields: Dict[str, str] | None = None,
    compare_to_remote: bool = True,
    ignore_fields: List[str] | None = None,
) -> Dict[str, Any]:
    records = await binding_manager.get_all_records(node_type)
    checked_pairs = 0
    depend_fields = dict(depend_fields or {})
    id_resolver = IDResolver(local_collection, remote_collection, binding_manager)
    validator = SchemaDiffValidator(
        schema_name=node_type,
        ignore_fields=ignore_fields,
    )
    data_id_map = await build_data_id_normalization_map(
        node_type=node_type,
        local_collection=local_collection,
        remote_collection=remote_collection,
        binding_manager=binding_manager,
    )

    for record in records:
        local_id = record.local_id
        remote_id = record.remote_id
        if not local_id or not remote_id:
            continue

        local_node = local_collection.get_by_node_id(local_id)
        remote_node = remote_collection.get_by_node_id(remote_id)
        checked_pairs += 1

        if local_node is None or remote_node is None:
            mismatches.append(
                f"pair_missing(local_node={bool(local_node)}, remote_node={bool(remote_node)}, local_id={local_id}, remote_id={remote_id})"
            )
            continue

        local_data = local_node.get_data() or {}
        remote_data = remote_node.get_data() or {}

        # 与 create/update 保持同一依赖ID解析函数：IDResolver.resolve_and_validate。
        # compare_to_remote=True  -> local(data) 先转 remote 口径后比较
        # compare_to_remote=False -> remote(data) 先转 local 口径后比较
        if depend_fields:
            if compare_to_remote:
                resolved_local, _ = await id_resolver.resolve_and_validate(
                    data=local_data,
                    node_type=node_type,
                    depend_fields=depend_fields,
                    to_remote=True,
                )
                if resolved_local is not None:
                    local_data = resolved_local
            else:
                resolved_remote, _ = await id_resolver.resolve_and_validate(
                    data=remote_data,
                    node_type=node_type,
                    depend_fields=depend_fields,
                    to_remote=False,
                )
                if resolved_remote is not None:
                    remote_data = resolved_remote

        local_payload = strategy.normalize_compare_payload(local_data, data_id_map)
        remote_payload = strategy.normalize_compare_payload(remote_data, data_id_map)
        diff_map = validator.compare_payloads(
            local_payload,
            remote_payload,
            sample_id=f"{local_id}->{remote_id}",
            schema_refs=[node_type],
        )
        if diff_map:
            detail_parts = []
            for field_name, values in diff_map.items():
                local_text = _compact_repr(values.get("local"))
                remote_text = _compact_repr(values.get("remote"))
                detail_parts.append(f"{field_name}{{local:{local_text},remote:{remote_text}}}")
            detail = "; ".join(detail_parts) if detail_parts else "payload differs"
            _append_post_check_error(local_node, f"post_check diff: {detail}")
            _append_post_check_error(remote_node, f"post_check diff: {detail}")

    report = validator.build_report() if checked_pairs else {
        "schema_name": node_type,
        "pairs_compared": 0,
        "mismatched_pairs": 0,
        "ignore_fields": [],
        "fields": [],
    }

    # 将字段统计补回到结果里，供 summary 输出。
    report["fields"] = report.get("fields", [])

    result = {
        "ok": report["mismatched_pairs"] == 0,
        "checked_pairs": checked_pairs,
        "mismatch_count": report["mismatched_pairs"],
        "fields": report["fields"],
        "schema_name": report["schema_name"],
        "ignore_fields": report["ignore_fields"],
    }

    return result
