"""Read-only evidence enrichment and source-wiring previews."""

from __future__ import annotations

from typing import Any

from services.ai_exception_contract import LEGACY_HUMAN_REVIEW_REQUIRED_COUNT_KEY
from services.pchome_mapping_backlog.contracts import (
    _ai_exception_compatibility_fields,
    _evidence_requires_ai_exception,
)
from services.pchome_mapping_backlog.policies import (
    EVIDENCE_ENRICHMENT_PREVIEW_POLICY,
    EVIDENCE_SOURCE_PREVIEW_POLICY,
    PCHOME_FETCH_MAX_BATCH_SIZE,
    PRODUCT_PAGE_EVIDENCE_PARSER_POLICY,
)
from services.pchome_mapping_backlog.reporter import (
    build_pchome_mapping_operator_preview,
)


def _field_enrichment_sources(field: str) -> list[dict[str, Any]]:
    source_map = {
        "image": [
            {
                "source": "PChome product page structured data",
                "mode": "future_read_only_fetch",
                "writes_database": False,
                "expected_output": "primary product image URL",
            },
            {
                "source": "existing marketplace catalog payload",
                "mode": "reuse_if_present",
                "writes_database": False,
                "expected_output": "cached image_url",
            },
        ],
        "availability": [
            {
                "source": "PChome product page offer availability",
                "mode": "future_read_only_fetch",
                "writes_database": False,
                "expected_output": "in_stock / out_of_stock / unknown",
            },
            {
                "source": "merchant listing structured data",
                "mode": "future_read_only_parse",
                "writes_database": False,
                "expected_output": "schema.org Offer availability",
            },
        ],
        "unit_price_or_package_basis": [
            {
                "source": "deterministic product title parser",
                "mode": "local_parse_preview",
                "writes_database": False,
                "expected_output": "size, count, unit label, package basis",
            },
            {
                "source": "external_price.price_basis",
                "mode": "reuse_if_present",
                "writes_database": False,
                "expected_output": "total_price / unit_price",
            },
        ],
        "price": [
            {
                "source": "growth opportunity payload",
                "mode": "reuse_if_present",
                "writes_database": False,
                "expected_output": "PChome listed price",
            },
        ],
    }
    return source_map.get(field, [])


def _source_plan_for_field(field: str, missing_count: int) -> dict[str, Any]:
    plans = {
        "image": {
            "payload_keys_checked": ["image_url", "image", "product_image_url"],
            "preferred_current_source": "existing marketplace catalog payload",
            "future_read_only_fetch_gate": {
                "method": "GET",
                "allowed_domain": "24h.pchome.com.tw",
                "product_url_required": True,
                "parse_targets": [
                    "schema.org Product.image",
                    "og:image",
                    "primary product image",
                ],
                "check_mode_parser": PRODUCT_PAGE_EVIDENCE_PARSER_POLICY,
                "fetches_external_sites_in_preview": False,
                "writes_database": False,
            },
        },
        "availability": {
            "payload_keys_checked": [
                "availability",
                "stock_status",
                "is_available",
            ],
            "preferred_current_source": "existing marketplace catalog payload",
            "future_read_only_fetch_gate": {
                "method": "GET",
                "allowed_domain": "24h.pchome.com.tw",
                "product_url_required": True,
                "parse_targets": [
                    "schema.org Offer.availability",
                    "merchant listing offer availability",
                ],
                "check_mode_parser": PRODUCT_PAGE_EVIDENCE_PARSER_POLICY,
                "fetches_external_sites_in_preview": False,
                "writes_database": False,
            },
        },
        "price": {
            "payload_keys_checked": [
                "pchome_price",
                "external_price.pchome_price",
                "review_candidate.pchome_price",
            ],
            "preferred_current_source": "growth opportunity payload",
            "future_read_only_fetch_gate": None,
            "payload_mapping_probe": {
                "goal": "Confirm whether missing price is a source payload gap or summary field mapping gap.",
                "fetches_external_sites_in_preview": False,
                "writes_database": False,
            },
        },
    }
    plan = dict(plans.get(field, {}))
    if not plan:
        return {}
    plan["field"] = field
    plan["status"] = (
        "missing_in_current_payload"
        if missing_count
        else "covered_by_current_payload"
    )
    plan["missing_count"] = missing_count
    return plan


def _build_fetch_gate_candidates(
    tasks: list[dict[str, Any]],
) -> list[dict[str, Any]]:
    candidates = []
    for task in tasks:
        missing_fields = set(task.get("missing_fields") or [])
        fetch_fields = [
            field
            for field in ("image", "availability")
            if field in missing_fields
        ]
        if not fetch_fields:
            continue
        candidates.append(
            {
                "pchome_product_id": task.get("pchome_product_id") or "",
                "product_name": task.get("product_name") or "",
                "product_url": task.get("product_url"),
                "fields": fetch_fields,
                "method": "GET",
                "allowed_domain": "24h.pchome.com.tw",
                "executes_fetch_in_preview": False,
                "writes_database": False,
            }
        )
    return candidates[:PCHOME_FETCH_MAX_BATCH_SIZE]


def _build_evidence_task(target: dict[str, Any], lane: str) -> dict[str, Any]:
    evidence = target.get("evidence_completeness") or {}
    missing_fields = list(evidence.get("missing_fields") or [])
    blocking_missing_fields = list(evidence.get("blocking_missing_fields") or [])
    enrichment_steps = [
        {
            "field": field,
            "blocking": field in blocking_missing_fields,
            "sources": _field_enrichment_sources(field),
        }
        for field in missing_fields
    ]
    ai_exception_required = _evidence_requires_ai_exception(evidence)

    return {
        "lane": lane,
        "pchome_product_id": target.get("pchome_product_id") or "",
        "product_name": target.get("product_name") or "",
        "product_url": target.get("product_url") or evidence.get("product_url"),
        "sales_7d": target.get("sales_7d"),
        "priority_score": target.get("priority_score"),
        "action_code": target.get("action_code"),
        "evidence_score": evidence.get("score"),
        "present_fields": list(evidence.get("present_fields") or []),
        "missing_fields": missing_fields,
        "blocking_missing_fields": blocking_missing_fields,
        "auto_accept_ready": bool(evidence.get("auto_accept_ready")),
        **_ai_exception_compatibility_fields(ai_exception_required),
        "unit_package_basis": evidence.get("unit_package_basis"),
        "enrichment_steps": enrichment_steps,
    }


def build_pchome_evidence_enrichment_preview(
    payload: dict[str, Any],
    batch_size: int = 5,
) -> dict[str, Any]:
    """Build a read-only evidence enrichment package for mapping targets."""
    operator_preview = build_pchome_mapping_operator_preview(
        payload,
        batch_size=batch_size,
    )
    operator_batch = operator_preview.get("operator_batch") or {}
    direct_targets = list(operator_batch.get("direct_mapping_targets") or [])
    review_targets = list(operator_batch.get("review_candidate_targets") or [])
    evidence_tasks = [
        *[
            _build_evidence_task(target, "direct_mapping")
            for target in direct_targets
        ],
        *[
            _build_evidence_task(target, "review_candidate")
            for target in review_targets
        ],
    ]
    tasks_with_blockers = [
        task for task in evidence_tasks if task.get("blocking_missing_fields")
    ]
    missing_field_counts: dict[str, int] = {}
    for task in evidence_tasks:
        for field in task.get("missing_fields") or []:
            missing_field_counts[field] = missing_field_counts.get(field, 0) + 1

    if tasks_with_blockers:
        result = "NEEDS_EVIDENCE_ENRICHMENT"
    elif evidence_tasks:
        result = "EVIDENCE_PREVIEW_READY"
    else:
        result = "NO_TARGETS"

    return {
        "policy": EVIDENCE_ENRICHMENT_PREVIEW_POLICY,
        "result": result,
        "success": bool(operator_preview.get("success")),
        "generated_at": operator_preview.get("generated_at"),
        "source_policy": operator_preview.get("policy"),
        "stats": operator_preview.get("stats") or {},
        "summary": {
            "task_count": len(evidence_tasks),
            "tasks_with_blockers": len(tasks_with_blockers),
            "missing_field_counts": missing_field_counts,
            "auto_accept_ready_count": sum(
                1 for task in evidence_tasks if task.get("auto_accept_ready")
            ),
            LEGACY_HUMAN_REVIEW_REQUIRED_COUNT_KEY: 0,
            "primary_human_gate_count": 0,
            "ai_exception_required_count": sum(
                1
                for task in evidence_tasks
                if task.get("ai_exception_required")
            ),
        },
        "evidence_tasks": evidence_tasks,
        "external_benchmark_alignment": (
            operator_preview.get("external_benchmark_alignment") or {}
        ),
        "ai_automation_plan": {
            "policy": "ollama_first_read_only_evidence_assist",
            "llm_calls_in_preview": False,
            "gemini_allowed": False,
            "can_execute_write": False,
            "recommended_next_ai_task": "Generate deterministic identity anchors and evidence gap summaries after image and availability sources are wired.",
            "blocked_until": [
                "image evidence source is wired",
                "availability evidence source is wired",
                "unit/package parser preview is compared against production title samples",
            ],
        },
        "safety": {
            "read_only_preview": True,
            "fetches_external_sites": False,
            "writes_database": False,
            "executes_search": False,
            "dispatches_telegram": False,
            "llm_calls_in_preview": False,
            "requires_operator_write_approval": True,
        },
        "next_actions": [
            "Wire read-only image and availability enrichment before expanding auto-accept.",
            "Validate deterministic unit/package basis parsing for bundle-sensitive items.",
            "Keep DB writes behind the existing /api/ai/pchome-growth/backfill-momo-candidates write gate.",
        ],
    }


def build_pchome_evidence_source_preview(
    payload: dict[str, Any],
    batch_size: int = 5,
) -> dict[str, Any]:
    """Build a read-only source wiring preview for missing product evidence fields."""
    enrichment_preview = build_pchome_evidence_enrichment_preview(
        payload,
        batch_size=batch_size,
    )
    tasks = list(enrichment_preview.get("evidence_tasks") or [])
    fields = ["image", "availability", "price", "unit_price_or_package_basis"]
    field_counts = {}
    source_plans = {}
    for field in fields:
        missing_tasks = [
            task
            for task in tasks
            if field in (task.get("missing_fields") or [])
        ]
        field_counts[field] = {
            "missing_count": len(missing_tasks),
            "present_count": max(len(tasks) - len(missing_tasks), 0),
            "sample_missing_targets": [
                {
                    "pchome_product_id": task.get("pchome_product_id") or "",
                    "product_name": task.get("product_name") or "",
                    "product_url": task.get("product_url"),
                    "lane": task.get("lane"),
                }
                for task in missing_tasks[:3]
            ],
        }
        plan = _source_plan_for_field(field, len(missing_tasks))
        if plan:
            source_plans[field] = plan

    fetch_gate_candidates = _build_fetch_gate_candidates(tasks)
    if (
        field_counts["image"]["missing_count"]
        or field_counts["availability"]["missing_count"]
    ):
        result = "NEEDS_SOURCE_WIRING"
    elif field_counts["price"]["missing_count"]:
        result = "NEEDS_PAYLOAD_MAPPING_PROBE"
    elif tasks:
        result = "SOURCE_PREVIEW_READY"
    else:
        result = "NO_TARGETS"

    return {
        "policy": EVIDENCE_SOURCE_PREVIEW_POLICY,
        "result": result,
        "success": bool(enrichment_preview.get("success")),
        "generated_at": enrichment_preview.get("generated_at"),
        "source_policy": enrichment_preview.get("policy"),
        "stats": enrichment_preview.get("stats") or {},
        "summary": {
            "task_count": len(tasks),
            "field_counts": field_counts,
            "fetch_gate_candidate_count": len(fetch_gate_candidates),
        },
        "source_plans": source_plans,
        "fetch_gate_candidates": fetch_gate_candidates,
        "external_benchmark_alignment": (
            enrichment_preview.get("external_benchmark_alignment") or {}
        ),
        "ai_automation_plan": {
            "policy": "ollama_first_read_only_source_wiring_assist",
            "llm_calls_in_preview": False,
            "gemini_allowed": False,
            "can_execute_fetch": False,
            "can_execute_write": False,
            "recommended_next_ai_task": "Generate schema-aware parsers for image and availability after fetch-gate tests are accepted.",
        },
        "safety": {
            "read_only_preview": True,
            "fetches_external_sites": False,
            "writes_database": False,
            "executes_search": False,
            "dispatches_telegram": False,
            "llm_calls_in_preview": False,
            "requires_production_version_truth": True,
            "requires_fetch_gate_implementation_before_external_get": True,
        },
        "next_actions": [
            "Wire image source preview from existing payload keys before adding a controlled product-page fetch gate.",
            "Wire availability source preview from existing payload keys before adding a controlled Offer availability parser.",
            "Probe missing price rows through current payload mapping before any external fetch or write.",
        ],
    }
