"""Read-only PChome backlog reporting and operator preview projections."""

from __future__ import annotations

from typing import Any

from services.pchome_mapping_backlog.contracts import _ai_exception_compatibility_fields
from services.pchome_mapping_backlog.evidence import (
    _action_code,
    _action_label,
    _first_present,
    _pchome_product_url,
    _to_float,
    parse_unit_package_basis,
)
from services.pchome_mapping_backlog.policies import (
    BACKLOG_POLICY,
    EXTERNAL_BENCHMARK_REFERENCES,
    OPERATOR_PREVIEW_POLICY,
)


def _evidence_completeness(
    item: dict[str, Any],
    review_candidate: dict[str, Any],
    external_price: dict[str, Any],
) -> dict[str, Any]:
    product_id = str(item.get("pchome_product_id") or "").strip()
    product_name = str(item.get("product_name") or "").strip()
    product_url = _first_present(
        item.get("product_url"),
        item.get("pchome_url"),
        _pchome_product_url(product_id),
    )
    pchome_price = _first_present(
        item.get("pchome_price"),
        external_price.get("pchome_price"),
        review_candidate.get("pchome_price"),
    )
    image_url = _first_present(
        item.get("image_url"),
        item.get("image"),
        item.get("product_image_url"),
    )
    availability = _first_present(
        item.get("availability"),
        item.get("stock_status"),
        item.get("is_available"),
    )
    unit_package_basis = parse_unit_package_basis(product_name)
    parsed_unit_basis = (
        unit_package_basis
        if unit_package_basis.get("package_basis") != "insufficient"
        else None
    )
    unit_basis = _first_present(
        external_price.get("price_basis"),
        item.get("price_basis"),
        item.get("unit_label"),
        parsed_unit_basis,
    )
    unit_review_required = bool(unit_package_basis.get("risk_signals"))

    checks = [
        ("stable_product_id", bool(product_id), "required"),
        ("product_name", bool(product_name), "required"),
        ("product_url", bool(product_url), "required"),
        ("price", pchome_price is not None, "required"),
        ("image", bool(image_url), "strongly_recommended"),
        ("availability", availability is not None, "strongly_recommended"),
        (
            "unit_price_or_package_basis",
            bool(unit_basis),
            "required_when_bundle_or_unit_sensitive",
        ),
    ]
    present = [field for field, ok, _requirement in checks if ok]
    missing = [field for field, ok, _requirement in checks if not ok]
    blocking_missing = [
        field
        for field, ok, requirement in checks
        if not ok and requirement in {"required", "strongly_recommended"}
    ]
    score = round(len(present) / max(len(checks), 1) * 100, 1)

    ai_exception_required = (
        bool(blocking_missing)
        or bool(review_candidate)
        or not external_price
        or unit_review_required
    )

    return {
        "score": score,
        "present_fields": present,
        "missing_fields": missing,
        "blocking_missing_fields": blocking_missing,
        "auto_accept_ready": (
            not blocking_missing and bool(external_price) and not unit_review_required
        ),
        **_ai_exception_compatibility_fields(ai_exception_required),
        "product_url": product_url,
        "image_url": image_url,
        "availability": availability,
        "unit_package_basis": unit_package_basis,
    }


def compact_mapping_item(item: dict[str, Any]) -> dict[str, Any]:
    review_candidate = item.get("review_candidate") or {}
    external_price = item.get("external_price") or {}
    product_id = str(item.get("pchome_product_id") or "")
    product_url = _first_present(
        item.get("product_url"),
        item.get("pchome_url"),
        _pchome_product_url(product_id),
    )
    return {
        "pchome_product_id": product_id,
        "product_url": product_url,
        "product_name": item.get("product_name") or "",
        "sales_7d": round(_to_float(item.get("sales_7d")), 2),
        "sales_delta_pct": item.get("sales_delta_pct"),
        "priority_score": item.get("priority_score"),
        "pchome_price": item.get("pchome_price"),
        "action_code": _action_code(item),
        "action_label": _action_label(item),
        "review_candidate": {
            "id": review_candidate.get("id"),
            "momo_sku": review_candidate.get("momo_sku"),
            "momo_name": review_candidate.get("momo_name"),
            "quality_score": review_candidate.get("quality_score"),
            "gap_pct": review_candidate.get("gap_pct"),
        }
        if review_candidate
        else None,
        "external_price": {
            "momo_sku": external_price.get("momo_sku"),
            "momo_name": external_price.get("momo_name"),
            "price_basis": external_price.get("price_basis"),
            "gap_pct": external_price.get("gap_pct"),
            "data_source_label": external_price.get("data_source_label"),
            "updated_at": external_price.get("updated_at"),
        }
        if external_price
        else None,
        "evidence_completeness": _evidence_completeness(
            item,
            review_candidate,
            external_price,
        ),
        "reason_lines": list(item.get("reason_lines") or [])[:3],
    }


def _build_external_benchmark_alignment() -> dict[str, Any]:
    return {
        "references": EXTERNAL_BENCHMARK_REFERENCES,
        "required_evidence_fields": [
            {
                "field": "stable_product_id",
                "current_payload": "pchome_product_id",
                "status": "present",
                "why": "Stable IDs preserve mapping history and make post-run readback comparable.",
            },
            {
                "field": "product_name",
                "current_payload": "product_name",
                "status": "present",
                "why": "Exact title/name matching is the first identity anchor for operator review.",
            },
            {
                "field": "product_url",
                "current_payload": "derived_from_pchome_product_id",
                "status": "present_for_pchome",
                "why": "Operators need a direct product page path for visual confirmation.",
            },
            {
                "field": "price",
                "current_payload": "pchome_price/external_price",
                "status": "partial",
                "why": "Offer price and currency are required before a candidate can become decision-ready.",
            },
            {
                "field": "image",
                "current_payload": None,
                "status": "missing_in_current_growth_payload",
                "why": "Image evidence should be added before high-volume auto-accept expansion.",
            },
            {
                "field": "availability",
                "current_payload": None,
                "status": "missing_in_current_growth_payload",
                "why": "Availability prevents matching stale or non-purchasable offers.",
            },
            {
                "field": "unit_price_or_package_basis",
                "current_payload": (
                    "external_price.price_basis or deterministic title parser preview"
                ),
                "status": "parser_preview_available",
                "why": "Unit price and package basis protect bundles, variants, and volume-size comparisons.",
            },
        ],
        "operator_review_principles": [
            "Separate direct mapping, review candidate, and already comparable items.",
            "Do not auto-accept variants, colors, bundles, or catalog offers without explicit evidence.",
            "Keep search/query support exact-title friendly so copied product names and model terms remain useful.",
        ],
    }


def _build_ai_automation_plan(
    selected_direct: list[dict[str, Any]],
    selected_review: list[dict[str, Any]],
) -> dict[str, Any]:
    return {
        "policy": "ollama_first_read_only_ai_assist",
        "llm_calls_in_preview": False,
        "gemini_allowed": False,
        "provider_order": [
            "GCP-A 34.87.90.216:11434",
            "GCP-B 34.21.145.224:11434",
            "111 192.168.0.111:11434",
        ],
        "automation_readiness": {
            "direct_mapping_targets": len(selected_direct),
            "review_candidate_targets": len(selected_review),
            "can_generate_operator_summary": bool(selected_direct or selected_review),
            "can_execute_write": False,
        },
        "steps": [
            {
                "name": "identity_anchor_extraction",
                "mode": "deterministic_first_ollama_assist_later",
                "writes_database": False,
                "output": "brand/product_line/spec/package/variant anchors for each selected target",
            },
            {
                "name": "candidate_search_plan",
                "mode": "rule_based_query_pack",
                "writes_database": False,
                "output": "exact title, brand plus product line, and spec-preserving search terms",
            },
            {
                "name": "operator_decision_summary",
                "mode": "ollama_first_after_write_gate_only",
                "writes_database": False,
                "output": "plain-language review reason, evidence gaps, and post-write readback checklist",
            },
            {
                "name": "post_write_readback",
                "mode": "deterministic_metrics",
                "writes_database": False,
                "output": "mapping_rate, direct_mapping_count, review_candidate_count, mapped_count delta",
            },
        ],
        "ai_exception_required_for": [
            "missing image or availability evidence",
            "variant/color/fragrance/shade/package ambiguity",
            "unit-price or bundle-sensitive comparisons",
            "any candidate not meeting exact identity evidence",
        ],
    }


def summarize_pchome_mapping_backlog(payload: dict[str, Any]) -> dict[str, Any]:
    stats = payload.get("stats") or {}
    opportunities = [
        item
        for item in payload.get("opportunities") or []
        if isinstance(item, dict)
    ]
    needs_mapping = [item for item in opportunities if not item.get("external_price")]
    review_candidates = [
        item for item in needs_mapping if item.get("review_candidate")
    ]
    direct_mapping = [
        item
        for item in needs_mapping
        if _action_code(item) == "map_external_product"
        and not item.get("review_candidate")
    ]
    mapped = [item for item in opportunities if item.get("external_price")]

    action_counts: dict[str, int] = {}
    sales_by_action: dict[str, float] = {}
    for item in opportunities:
        label = _action_label(item)
        action_counts[label] = action_counts.get(label, 0) + 1
        sales_by_action[label] = round(
            sales_by_action.get(label, 0.0) + _to_float(item.get("sales_7d")),
            2,
        )

    candidate_count = int(stats.get("candidate_count") or len(opportunities))
    mapped_count = int(stats.get("mapped_count") or len(mapped))
    needs_mapping_count = int(stats.get("needs_mapping_count") or len(needs_mapping))
    mapping_rate = stats.get("mapping_rate")
    if mapping_rate is None:
        mapping_rate = round(mapped_count / max(candidate_count, 1) * 100, 1)

    top_needs_mapping = sorted(
        needs_mapping,
        key=lambda item: (
            _to_float(item.get("sales_7d")),
            _to_float(item.get("priority_score")),
        ),
        reverse=True,
    )[:10]
    top_review_candidates = sorted(
        review_candidates,
        key=lambda item: _to_float(
            (item.get("review_candidate") or {}).get("quality_score")
        ),
        reverse=True,
    )[:10]

    if not payload.get("success", False):
        result = "BLOCKED"
    elif needs_mapping_count > 0:
        result = "NEEDS_MAPPING"
    else:
        result = "PASS"

    return {
        "policy": BACKLOG_POLICY,
        "result": result,
        "success": bool(payload.get("success")),
        "generated_at": payload.get("generated_at"),
        "cache_state": payload.get("cache_state"),
        "system_name": payload.get("system_name"),
        "message": payload.get("message"),
        "stats": {
            "candidate_count": candidate_count,
            "mapped_count": mapped_count,
            "mapping_rate": mapping_rate,
            "needs_mapping_count": needs_mapping_count,
            "review_candidate_count": int(
                stats.get("review_candidate_count") or len(review_candidates)
            ),
            "latest_sales_date": stats.get("latest_sales_date"),
            "overall_latest_sales_date": stats.get("overall_latest_sales_date"),
            "overall_sales_7d": stats.get("overall_sales_7d"),
            "opportunity_sales_7d": stats.get("opportunity_sales_7d"),
            "action_counts": dict(stats.get("action_counts") or action_counts),
            "action_code_counts": dict(stats.get("action_code_counts") or {}),
            "external_data_source_counts": dict(
                stats.get("external_data_source_counts") or {}
            ),
        },
        "backlog": {
            "direct_mapping_count": len(direct_mapping),
            "review_candidate_count": len(review_candidates),
            "mapped_opportunity_count": len(mapped),
            "sales_by_action": sales_by_action,
            "top_needs_mapping": [
                compact_mapping_item(item) for item in top_needs_mapping
            ],
            "top_review_candidates": [
                compact_mapping_item(item) for item in top_review_candidates
            ],
        },
        "next_actions": [
            "Run the production version truth guard before changing or deploying.",
            "Handle direct mapping items first; they have no verified external price yet.",
            "Review candidate items next; they already have MOMO candidates but need same-item confirmation.",
            "Keep this report read-only until an explicit DB-write operator run is approved.",
        ],
    }


def build_pchome_mapping_operator_preview(
    payload: dict[str, Any],
    batch_size: int = 5,
) -> dict[str, Any]:
    """Build a read-only operator run package for the direct mapping backlog."""
    summary = summarize_pchome_mapping_backlog(payload)
    backlog = summary.get("backlog") or {}
    direct_items = [
        item
        for item in backlog.get("top_needs_mapping") or []
        if item.get("action_code") == "map_external_product"
    ]
    review_items = list(backlog.get("top_review_candidates") or [])
    batch_size = max(1, min(int(batch_size or 5), 8))
    selected_direct = direct_items[:batch_size]
    selected_review = review_items[:batch_size]

    if selected_direct:
        result = "READY_FOR_OPERATOR_PREVIEW"
    elif selected_review:
        result = "REVIEW_CANDIDATES_ONLY"
    else:
        result = "NO_DIRECT_MAPPING_TARGETS"

    return {
        "policy": OPERATOR_PREVIEW_POLICY,
        "result": result,
        "success": bool(summary.get("success")),
        "generated_at": summary.get("generated_at"),
        "stats": summary.get("stats") or {},
        "backlog": {
            "direct_mapping_count": int(backlog.get("direct_mapping_count") or 0),
            "review_candidate_count": int(
                backlog.get("review_candidate_count") or 0
            ),
            "mapped_opportunity_count": int(
                backlog.get("mapped_opportunity_count") or 0
            ),
        },
        "operator_batch": {
            "batch_size": batch_size,
            "selected_direct_mapping_count": len(selected_direct),
            "selected_review_candidate_count": len(selected_review),
            "direct_mapping_targets": selected_direct,
            "review_candidate_targets": selected_review,
        },
        "command_preview": {
            "method": "POST",
            "endpoint": "/api/ai/pchome-growth/backfill-momo-candidates",
            "payload": {"limit": min(batch_size, 8)},
            "executes_search": True,
            "writes_database": True,
            "write_gate_required": True,
        },
        "external_benchmark_alignment": _build_external_benchmark_alignment(),
        "ai_automation_plan": _build_ai_automation_plan(
            selected_direct,
            selected_review,
        ),
        "safety": {
            "read_only_preview": True,
            "executes_search": False,
            "writes_database": False,
            "dispatches_telegram": False,
            "requires_production_version_truth": True,
            "requires_operator_write_approval": True,
        },
        "required_before_execute": [
            "Run production version truth guard and keep production /health as latest truth.",
            "Confirm the selected direct mapping targets are the intended PChome products.",
            "Confirm DB-write authorization for /api/ai/pchome-growth/backfill-momo-candidates.",
            "Run post-write mapping backlog readback and compare direct_mapping_count / mapped_count.",
        ],
        "acceptance_criteria": [
            "direct_mapping_count decreases, or review_candidate_count increases with named MOMO candidates.",
            "mapped_count or mapping_rate increases only when a verified external price is written.",
            "No Gemini, Telegram dispatch, scheduler mutation, or unrelated DB write is part of this run.",
        ],
    }
