#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""PChome 高業績商品主動反查 MOMO 候選，寫入外部報價層。"""

from __future__ import annotations

import os
from typing import Any, Callable


def _int_env(name: str, default: int, *, minimum: int, maximum: int) -> int:
    try:
        value = int(os.getenv(name, str(default)))
    except (TypeError, ValueError):
        value = default
    return max(minimum, min(value, maximum))


def _float_env(name: str, default: float, *, minimum: float, maximum: float) -> float:
    try:
        value = float(os.getenv(name, str(default)))
    except (TypeError, ValueError):
        value = default
    return max(minimum, min(value, maximum))


def candidate_auto_compare_type(candidate: dict[str, Any]) -> str:
    auto_type = str(candidate.get("auto_compare_type") or "").strip()
    if auto_type in {"total_price", "unit_price"}:
        return auto_type
    if candidate.get("can_auto_compare") is True:
        return "total_price"
    return "manual_review"


def build_momo_backfill_targets(payload: dict[str, Any], limit: int) -> list[dict[str, Any]]:
    opportunities = list((payload or {}).get("opportunities") or [])
    targets: list[dict[str, Any]] = []
    for item in opportunities:
        action = item.get("recommended_action") or {}
        if item.get("external_price"):
            continue
        if action.get("code") != "map_external_product":
            continue
        product_id = str(item.get("pchome_product_id") or "").strip()
        product_name = str(item.get("product_name") or "").strip()
        if not product_id or not product_name:
            continue
        targets.append({
            "product_id": product_id,
            "name": product_name,
            "price": item.get("pchome_price"),
            "sales_7d": item.get("sales_7d"),
            "priority_score": item.get("priority_score"),
        })
        if len(targets) >= limit:
            break
    return targets


def _default_build_payload(engine, limit: int) -> dict[str, Any]:
    from services.pchome_revenue_growth_service import build_pchome_growth_opportunities

    return build_pchome_growth_opportunities(engine, limit=limit)


def _default_search_candidates(targets: list[dict[str, Any]], limit: int):
    from services.momo_crawler import search_momo_products_for_pchome_products

    return search_momo_products_for_pchome_products(
        targets,
        max_products=limit,
        limit_per_product=_int_env(
            "PCHOME_GROWTH_MOMO_BACKFILL_LIMIT_PER_TERM",
            8,
            minimum=3,
            maximum=12,
        ),
        max_terms_per_product=_int_env(
            "PCHOME_GROWTH_MOMO_BACKFILL_MAX_TERMS",
            8,
            minimum=3,
            maximum=10,
        ),
        min_score=_float_env(
            "PCHOME_GROWTH_MOMO_BACKFILL_MIN_SCORE",
            0.45,
            minimum=0.35,
            maximum=0.8,
        ),
    )


def _default_sync_candidates(engine, candidates: list[dict[str, Any]]) -> dict[str, Any]:
    from services.external_market_offer_service import sync_targeted_momo_candidates_to_external_offers

    return sync_targeted_momo_candidates_to_external_offers(engine, candidates, dry_run=False)


def _default_sync_review_candidates(engine, candidates: list[dict[str, Any]]) -> dict[str, Any]:
    from services.external_market_offer_service import sync_targeted_momo_review_candidates_to_external_offers

    return sync_targeted_momo_review_candidates_to_external_offers(engine, candidates, dry_run=False)


def run_pchome_growth_momo_backfill(
    engine,
    *,
    limit: int = 12,
    build_payload_func: Callable[[Any, int], dict[str, Any]] | None = None,
    search_func: Callable[[list[dict[str, Any]], int], tuple[bool, str, list[dict[str, Any]]]] | None = None,
    sync_func: Callable[[Any, list[dict[str, Any]]], dict[str, Any]] | None = None,
    sync_review_func: Callable[[Any, list[dict[str, Any]]], dict[str, Any]] | None = None,
) -> dict[str, Any]:
    """補高業績 PChome 商品的 MOMO 對應。

    不呼叫 LLM，只搜尋 MOMO 候選，並只把可自動判斷的 total_price / unit_price
    寫入 external_offers；需人工確認的候選會以 needs_review 保存，不進價格判斷。
    """
    limit = max(1, min(int(limit or 12), 20))
    build_payload = build_payload_func or _default_build_payload
    search_candidates = search_func or _default_search_candidates
    sync_candidates = sync_func or _default_sync_candidates
    sync_review_candidates = sync_review_func or _default_sync_review_candidates

    before_payload = build_payload(engine, max(limit, 16))
    targets = build_momo_backfill_targets(before_payload, limit)
    if not targets:
        return {
            "success": True,
            "message": "目前高業績清單沒有需要補 MOMO 對應的商品。",
            "data": {
                "scanned_products": 0,
                "target_count": 0,
                "candidate_count": 0,
                "exact_compare_count": 0,
                "unit_compare_count": 0,
                "auto_compare_count": 0,
                "review_count": 0,
                "external_offer_sync": {
                    "success": True,
                    "status": "not_needed",
                    "written_count": 0,
                    "message": "沒有需要同步的自動候選。",
                },
                "review_candidate_sync": {
                    "success": True,
                    "status": "not_needed",
                    "written_count": 0,
                    "message": "沒有需要保存的待確認候選。",
                },
                "before_stats": before_payload.get("stats") or {},
                "after_stats": before_payload.get("stats") or {},
                "targets": [],
                "review_candidates": [],
            },
        }

    search_success, search_message, candidates = search_candidates(targets, limit)
    candidates = list(candidates or [])
    exact_candidates = [
        item for item in candidates
        if candidate_auto_compare_type(item) == "total_price"
    ]
    unit_candidates = [
        item for item in candidates
        if candidate_auto_compare_type(item) == "unit_price"
    ]
    review_candidates = [
        item for item in candidates
        if candidate_auto_compare_type(item) not in {"total_price", "unit_price"}
    ]
    auto_candidates = [*exact_candidates, *unit_candidates]
    external_offer_sync = {
        "success": True,
        "status": "not_found",
        "written_count": 0,
        "message": "已搜尋 MOMO，但尚未找到可自動寫入的同款或單位價候選。",
    }
    if auto_candidates:
        external_offer_sync = sync_candidates(engine, auto_candidates)
    review_candidate_sync = {
        "success": True,
        "status": "not_found",
        "written_count": 0,
        "message": "沒有需要保存的待確認候選。",
    }
    if review_candidates:
        review_candidate_sync = sync_review_candidates(engine, review_candidates)

    after_payload = build_payload(engine, max(limit, 16))
    written_count = int(external_offer_sync.get("written_count") or 0)
    message = (
        f"已掃描 {len(targets)} 個高業績商品，找到 {len(candidates)} 筆 MOMO 候選，"
        f"自動寫入 {written_count} 筆。"
    )
    if not search_success and not candidates:
        message = search_message or "已搜尋 MOMO，但沒有找到可用候選。"

    return {
        "success": True,
        "message": message,
        "data": {
            "search_success": bool(search_success),
            "search_message": search_message,
            "scanned_products": len(targets),
            "target_count": len(targets),
            "candidate_count": len(candidates),
            "exact_compare_count": len(exact_candidates),
            "unit_compare_count": len(unit_candidates),
            "auto_compare_count": len(auto_candidates),
            "review_count": len(review_candidates),
            "external_offer_sync": external_offer_sync,
            "review_candidate_sync": review_candidate_sync,
            "before_stats": before_payload.get("stats") or {},
            "after_stats": after_payload.get("stats") or {},
            "targets": targets[:8],
            "review_candidates": review_candidates[:8],
        },
    }
