from __future__ import annotations

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool

from app.services.document_intelligence import DocumentIntelligenceService, build_document_insight


def test_build_document_insight_prefers_transport_for_didi_text_with_hotel_noise() -> None:
    insight = build_document_insight(
        filename="didi-trip.png",
        summary="滴滴出行行程单",
        text="滴滴出行电子发票 订单号 12345678 上车点 深圳湾 下车点 后海 全季酒店 里程 12.4 公里 金额 48 元",
    )

    assert insight.document_type == "taxi_receipt"
    assert insight.document_type_label == "出租车/网约车票据"
    assert insight.scene_code == "transport"
    assert any(field.label == "金额" and field.value == "48元" for field in insight.fields)


def test_document_intelligence_service_uses_rule_result_when_preview_available() -> None:
    engine = create_engine(
        "sqlite+pysqlite:///:memory:",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    session = sessionmaker(bind=engine, autoflush=False, autocommit=False)()
    try:
        insight = DocumentIntelligenceService(session).build_document_insight(
            filename="mixed-noise.png",
            summary="OCR 混入酒店名称",
            text="全季酒店 滴滴出行 订单号 12345678 上车 下车 金额 52 元",
            preview_data_url="data:image/png;base64,ZmFrZQ==",
        )
    finally:
        session.close()

    assert insight.document_type == "taxi_receipt"
    assert insight.classification_source == "rule"


def test_document_intelligence_extracts_larger_decimal_amount_from_multiple_candidates() -> None:
    insight = build_document_insight(
        filename="taxi-amount.png",
        summary="滴滴出行电子行程单",
        text="滴滴出行 支付金额 1 元，实付 13.4 元，订单号 12345678",
    )

    assert any(field.label == "金额" and field.value == "13.4元" for field in insight.fields)


def test_document_intelligence_extracts_hotel_total_fee_instead_of_date_year() -> None:
    insight = build_document_insight(
        filename="hotel-invoice.png",
        summary="酒店住宿票据",
        text="北京中心酒店 金额 2026-02-20 入住 总费用是828元 离店日期 2026-02-21",
    )

    assert insight.document_type == "hotel_invoice"
    assert any(field.label == "金额" and field.value == "828元" for field in insight.fields)
    assert not any(field.label == "金额" and field.value == "2026元" for field in insight.fields)


def test_document_intelligence_prefers_train_ticket_for_railway_e_ticket_invoice_text() -> None:
    insight = build_document_insight(
        filename="铁路电子客票.pdf",
        summary="电子发票（铁路电子客票）",
        text=(
            "电子发票（铁路电子客票）\n"
            "发票号码:26319166100006175398\n"
            "上海虹桥站\n"
            "武汉站\n"
            "G456\n"
            "二等座\n"
            "票价:￥354.00"
        ),
    )

    assert insight.document_type == "train_ticket"
    assert insight.document_type_label == "火车/高铁票"
    assert insight.scene_code == "travel"
    assert any(field.label == "金额" and field.value == "354元" for field in insight.fields)


def test_document_intelligence_train_ticket_uses_railway_merchant_not_invoice_title() -> None:
    insight = build_document_insight(
        filename="2月20_武汉-上海.pdf",
        summary="电子发票（铁路电子客票）；发票监；统一 制",
        text=(
            "电子发票（铁路电子客票）\n"
            "发票号码:26429165800002785705 湖北\n"
            "开票日期:2026年05月18日\n"
            "武汉站 G458 上海虹桥站\n"
            "Wuhan Shanghaihongqiao\n"
            "2026年02月20日 07:55开 06车01B号 二等座\n"
            "票价:￥354.00\n"
            "4201061987****1615 曹笑竹\n"
            "电子客票号:6580061086021391007342026\n"
            "购买方名称:曹笑竹 统一社会信用代码:\n"
            "买票请到12306 发货请到95306\n"
            "中国铁路祝您旅途愉快"
        ),
    )

    assert insight.document_type == "train_ticket"
    fields = {field.label: field.value for field in insight.fields}
    assert fields["商户"] == "中国铁路"
    assert fields["金额"] == "354元"
    assert fields["列车出发时间"] == "2026-02-20 07:55"


def test_document_intelligence_recovers_train_ticket_from_english_station_ocr_text() -> None:
    insight = build_document_insight(
        filename="2月20_武汉-上海.pdf",
        summary=":26429165800002785705；:2026 05 18；Wuhan Shanghaihongqiao G458",
        text=(
            ":26429165800002785705\n"
            ":2026 05 18\n"
            "G458\n"
            "Wuhan\n"
            "Shanghaihongqiao\n"
            "2026 02 20 07:55\n"
            "06 01B\n"
            ": 354.00\n"
            "4201061987****1615\n"
            ":6580061086021391007342026\n"
            "12306 95306"
        ),
    )

    assert insight.document_type == "train_ticket"
    assert insight.document_type_label == "火车/高铁票"
    assert insight.scene_code == "travel"
    fields = {field.label: field.value for field in insight.fields}
    assert fields["金额"] == "354元"
    assert fields["列车出发时间"] == "2026-02-20 07:55"
    assert fields["车次/航班"] == "G458"
    assert fields["行程"] == "武汉-上海"


def test_document_intelligence_labels_train_ticket_date_as_train_departure_time() -> None:
    insight = build_document_insight(
        filename="铁路电子客票.pdf",
        summary="铁路电子客票",
        text=(
            "中国铁路电子客票 开票日期 2026-02-18 "
            "G456 上海虹桥-武汉 2026-02-20 08:30开 票价:￥354.00"
        ),
    )

    assert insight.document_type == "train_ticket"
    assert any(
        field.key == "date" and field.label == "列车出发时间" and field.value == "2026-02-20 08:30"
        for field in insight.fields
    )
    assert not any(field.label == "开票日期" for field in insight.fields)


def test_document_intelligence_service_keeps_rule_fields_without_model_correction() -> None:
    engine = create_engine(
        "sqlite+pysqlite:///:memory:",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    session = sessionmaker(bind=engine, autoflush=False, autocommit=False)()
    try:
        insight = DocumentIntelligenceService(session).build_document_insight(
            filename="didi-corrected.png",
            summary="滴滴出行电子行程单",
            text="滴滴出行 支付金额 1 元 订单号 12345678",
            preview_data_url="data:image/png;base64,ZmFrZQ==",
        )
    finally:
        session.close()

    assert any(field.label == "金额" and field.value == "1元" for field in insight.fields)
    assert insight.warnings == ()
