"""
Helpers para construir respuestas de scan y commit (formato unificado).
"""
from typing import Dict, Any, List, Optional


ERRORS_PREVIEW_LIMIT = 100
SUMMARY_LIMIT = 10


def _summarize_reasons(items: List[Dict[str, Any]], key_name: str) -> List[Dict[str, Any]]:
    counts: Dict[str, int] = {}
    for item in items:
        reason = str(item.get(key_name, "")).strip()
        if not reason:
            continue
        counts[reason] = counts.get(reason, 0) + 1
    ordered = sorted(counts.items(), key=lambda kv: kv[1], reverse=True)
    return [{"reason": reason, "count": count} for reason, count in ordered[:SUMMARY_LIMIT]]


def scan_result(
    job_id: str,
    processed_rows: int,
    error_count: int,
    errors_detail: List[Dict[str, Any]],
    total_rows_in_file: Optional[int] = None,
    message: Optional[str] = None,
) -> Dict[str, Any]:
    """Respuesta de scan_file (waiting_confirmation).
    Si total_rows_in_file no se pasa, se usa processed_rows como total (comportamiento anterior).
    """
    total = total_rows_in_file if total_rows_in_file is not None else processed_rows
    out: Dict[str, Any] = {
        "status": "waiting_confirmation",
        "job_id": job_id,
        "total_rows": total,
        "error_count": error_count,
        "valid_rows": processed_rows - error_count,
        # Para no saturar el front: devolvemos solo un preview.
        # El detalle completo se descarga desde CSV usando el job_id.
        "errors": errors_detail[:ERRORS_PREVIEW_LIMIT],
        "error_summary": _summarize_reasons([e for e in errors_detail if not e.get("warning")], "msg"),
    }
    if message:
        out["message"] = message
    return out


def commit_result(
    status: str,
    inserted: int,
    skipped_invalid: int,
    skipped_missing_fk: int,
    skipped_duplicate: int,
    skipped_details: List[Dict[str, Any]],
    message: Optional[str] = None,
    error: Optional[str] = None,
) -> Dict[str, Any]:
    """Respuesta de insert_valid_rows (finished / warning / failed)."""
    out = {
        "status": status,
        "inserted": inserted,
        "skipped_invalid": skipped_invalid,
        "skipped_missing_fk": skipped_missing_fk,
        "skipped_duplicate": skipped_duplicate,
        "skipped_details": skipped_details,
        "skipped_summary": _summarize_reasons(skipped_details, "reason"),
    }
    if message:
        out["message"] = message
    if error:
        out["error"] = error
    return out


def normalize_commit_status_payload(d: Dict[str, Any]) -> Dict[str, Any]:
    """
    Homogeneiza respuestas de commit CSV (finished / warning) al contrato usado por pedimentos:
    inserted, updated, skipped_*, skipped_details, skipped_summary, critical_reference_gaps,
    reference_state_ready. No modifica waiting_confirmation ni otros status.
    """
    if not isinstance(d, dict):
        return d
    st = d.get("status")
    if st not in ("finished", "warning"):
        return d
    out = dict(d)
    out.setdefault("inserted", 0)
    out.setdefault("updated", 0)
    out.setdefault("skipped_invalid", 0)
    out.setdefault("skipped_missing_fk", 0)
    out.setdefault("skipped_duplicate", 0)
    out.setdefault("skipped_missing_invoice", 0)
    details = out.get("skipped_details")
    if not isinstance(details, list):
        out["skipped_details"] = []
    else:
        out["skipped_details"] = details
    out.setdefault("critical_reference_gaps", 0)
    if "reference_state_ready" not in out:
        out["reference_state_ready"] = out.get("critical_reference_gaps", 0) == 0
    if "skipped_summary" not in out:
        out["skipped_summary"] = (
            _summarize_reasons(out["skipped_details"], "reason") if out["skipped_details"] else []
        )
    return out
