from __future__ import annotations

import re
from typing import Any

_CLEAR_TRAVEL_DOCUMENT_TYPES = {
    "flight_itinerary",
    "train_ticket",
    "ship_ticket",
    "hotel_invoice",
    "taxi_receipt",
    "parking_toll_receipt",
}
_CLEAR_TRAVEL_SCENE_CODES = {"travel", "hotel", "transport"}
_GOODS_DESCRIPTION_FIELD_KEYS = {
    "goodsname",
    "servicename",
    "itemname",
    "project",
    "productname",
    "description",
    "content",
    "expensecontent",
    "feeitem",
}
_GOODS_DESCRIPTION_LABEL_TOKENS = (
    "商品",
    "服务",
    "货物",
    "项目",
    "品名",
    "名称",
    "费用内容",
    "消费内容",
)
_VAGUE_KEYWORD_NEGATION_MARKERS = (
    "不含",
    "不包含",
    "不包括",
    "未包含",
    "不涉及",
    "不属于",
)


def collect_vague_goods_description_evidence(
    contexts: list[dict[str, Any]],
    keywords: list[str],
) -> dict[str, Any] | None:
    matched_keywords: list[str] = []
    matched_fields: list[dict[str, str]] = []

    for context in contexts:
        document_info = context.get("document_info") or {}
        if _is_clear_travel_document(document_info):
            continue

        field_values = _collect_goods_description_field_values(document_info)
        if field_values:
            for value in field_values:
                hits = _collect_non_negated_keyword_hits(value, keywords)
                for keyword in hits:
                    if keyword not in matched_keywords:
                        matched_keywords.append(keyword)
                if hits:
                    matched_fields.append(
                        {
                            "item_index": str(context.get("index") or ""),
                            "value": value[:80],
                        }
                    )
            continue

        fallback_text = f"{context.get('ocr_summary') or ''}\n{context.get('ocr_text') or ''}"
        hits = _collect_non_negated_keyword_hits(fallback_text, keywords)
        for keyword in hits:
            if keyword not in matched_keywords:
                matched_keywords.append(keyword)
        if hits:
            matched_fields.append(
                {
                    "item_index": str(context.get("index") or ""),
                    "value": "OCR全文兜底",
                }
            )

    if not matched_keywords:
        return None
    return {
        "matched_keywords": matched_keywords,
        "matched_fields": matched_fields[:5],
    }


def _is_clear_travel_document(document_info: dict[str, Any]) -> bool:
    document_type = str(document_info.get("document_type") or "").strip().lower()
    scene_code = str(document_info.get("scene_code") or "").strip().lower()
    return (
        document_type in _CLEAR_TRAVEL_DOCUMENT_TYPES
        or scene_code in _CLEAR_TRAVEL_SCENE_CODES
    )


def _collect_goods_description_field_values(document_info: dict[str, Any]) -> list[str]:
    values: list[str] = []
    for field in list(document_info.get("fields") or []):
        if not isinstance(field, dict):
            continue
        field_key = str(field.get("key") or "").strip().lower().replace("_", "")
        label = str(field.get("label") or "").replace(" ", "")
        value = str(field.get("value") or "").strip()
        if not value:
            continue
        if field_key in _GOODS_DESCRIPTION_FIELD_KEYS or any(
            token in label for token in _GOODS_DESCRIPTION_LABEL_TOKENS
        ):
            values.append(value)
    return values


def _collect_non_negated_keyword_hits(text: str, keywords: list[str]) -> list[str]:
    normalized = str(text or "")
    if not normalized:
        return []

    hits: list[str] = []
    for keyword in keywords:
        if not keyword:
            continue
        for match in re.finditer(re.escape(keyword), normalized):
            window = normalized[max(0, match.start() - 12): match.end() + 12]
            if any(marker in window for marker in _VAGUE_KEYWORD_NEGATION_MARKERS):
                continue
            hits.append(keyword)
            break
    return hits
