"""Privacy-safe five-company acceptance facts for the downstream processor."""

from __future__ import annotations

from datetime import date
from decimal import Decimal
from typing import Dict, List

from company_reports.contracts import (
    BatchSnapshot,
    BookingRoomItem,
    DailyVersionPin,
    FinanceFact,
)


REPORT_YEAR = 2026
REPORT_MONTH = 7
AS_OF_DATE = date(2026, 7, 31)


def _fact(
    record_id: int,
    *,
    business_date: date,
    daily_version_id: int,
    company_key: str,
    channel_key: str,
    group_code: str,
    block_code: str,
    arrival: date,
    departure: date,
    room_label: str,
    total_price: str,
) -> FinanceFact:
    return FinanceFact(
        daily_record_id=record_id,
        daily_version_id=daily_version_id,
        business_date=business_date,
        channel_key=channel_key,
        company_key=company_key,
        company_name=f"SYN-COMPANY-{company_key}",
        block_code=block_code,
        group_code_key=group_code,
        res_comment=group_code,
        room_category_label=room_label,
        arrival=arrival,
        departure=departure,
        nights=(departure - arrival).days,
        total_price=Decimal(total_price),
        booking_source_match_status="matched",
    )


def _room_item(
    item_no: int,
    *,
    group_code: str,
    parse_version_id: int,
    segment_no: int,
    arrival: date,
    departure: date,
    room_type: str,
    quantity: int,
) -> BookingRoomItem:
    return BookingRoomItem(
        group_code_key=group_code,
        parse_version_id=parse_version_id,
        segment_no=segment_no,
        arrival=arrival,
        departure=departure,
        nights=(departure - arrival).days,
        item_no=item_no,
        room_type_raw=room_type,
        quantity=quantity,
    )


def acceptance_snapshot() -> BatchSnapshot:
    """Return one synthetic month-end snapshot covering every accepted rule."""

    facts: List[FinanceFact] = []
    room_items: List[BookingRoomItem] = []

    lt_arrival = date(2026, 7, 7)
    lt_departure = date(2026, 7, 10)
    for record_id, room_label, price, block_code in (
        (101, "SYN-RM2", "900", "SYN-BLOCK-LT-A"),
        (102, "SYN-RM2", "900", "SYN-BLOCK-LT-A"),
        (103, "SYN-RM3", "3400", "SYN-BLOCK-LT-B"),
    ):
        facts.append(
            _fact(
                record_id,
                business_date=date(2026, 7, 8),
                daily_version_id=1008,
                company_key="LIAN TAI",
                channel_key="SYN-CHANNEL-LT",
                group_code="SYN-LT-0710",
                block_code=block_code,
                arrival=lt_arrival,
                departure=lt_departure,
                room_label=room_label,
                total_price=price,
            )
        )
    room_items.extend(
        (
            _room_item(
                1,
                group_code="SYN-LT-0710",
                parse_version_id=7101,
                segment_no=1,
                arrival=lt_arrival,
                departure=lt_departure,
                room_type="SYN-SUP-TWN-BF",
                quantity=2,
            ),
            _room_item(
                2,
                group_code="SYN-LT-0710",
                parse_version_id=7101,
                segment_no=1,
                arrival=lt_arrival,
                departure=lt_departure,
                room_type="SYN-SUP-TRP-BF",
                quantity=1,
            ),
        )
    )

    qbd_first_arrival = date(2026, 7, 7)
    qbd_first_departure = date(2026, 7, 10)
    for record_id, price in ((201, "900"), (202, "1800")):
        facts.append(
            _fact(
                record_id,
                business_date=date(2026, 7, 8),
                daily_version_id=1008,
                company_key="QBD",
                channel_key="SYN-CHANNEL-QBD",
                group_code="SYN-QBD-REPEAT",
                block_code="SYN-BLOCK-QBD-A",
                arrival=qbd_first_arrival,
                departure=qbd_first_departure,
                room_label="SYN-RM2",
                total_price=price,
            )
        )
    qbd_second_arrival = date(2026, 7, 17)
    qbd_second_departure = date(2026, 7, 20)
    for record_id in (203, 204, 205):
        facts.append(
            _fact(
                record_id,
                business_date=date(2026, 7, 18),
                daily_version_id=1018,
                company_key="QBD",
                channel_key="SYN-CHANNEL-QBD",
                group_code="SYN-QBD-REPEAT",
                block_code="SYN-BLOCK-QBD-B",
                arrival=qbd_second_arrival,
                departure=qbd_second_departure,
                room_label="SYN-RM2",
                total_price="900",
            )
        )
    room_items.extend(
        (
            _room_item(
                1,
                group_code="SYN-QBD-REPEAT",
                parse_version_id=7201,
                segment_no=1,
                arrival=qbd_first_arrival,
                departure=qbd_first_departure,
                room_type="SYN-SUP-TWN-BF",
                quantity=2,
            ),
            _room_item(
                1,
                group_code="SYN-QBD-REPEAT",
                parse_version_id=7201,
                segment_no=2,
                arrival=qbd_second_arrival,
                departure=qbd_second_departure,
                room_type="SYN-SUP-TWN-BF",
                quantity=3,
            ),
        )
    )

    dy_arrival = date(2026, 7, 18)
    dy_departure = date(2026, 7, 20)
    for record_id in (301, 302):
        facts.append(
            _fact(
                record_id,
                business_date=date(2026, 7, 18),
                daily_version_id=1018,
                company_key="SYN-UNMAPPED",
                channel_key="DY-AI-EASY-KB",
                group_code="SYN-DY-0720",
                block_code="SYN-BLOCK-DY-A",
                arrival=dy_arrival,
                departure=dy_departure,
                room_label="SYN-KB-RM",
                total_price="800",
            )
        )
    room_items.append(
        _room_item(
            1,
            group_code="SYN-DY-0720",
            parse_version_id=7301,
            segment_no=1,
            arrival=dy_arrival,
            departure=dy_departure,
            room_type="SYN-AI-EASY-TWN",
            quantity=2,
        )
    )

    fr_arrival = date(2026, 7, 27)
    fr_departure = date(2026, 7, 31)
    facts.append(
        _fact(
            401,
            business_date=date(2026, 7, 28),
            daily_version_id=1028,
            company_key="FENGRUN",
            channel_key="SYN-CHANNEL-FR",
            group_code="SYN-FR-0731",
            block_code="SYN-BLOCK-FR-A",
            arrival=fr_arrival,
            departure=fr_departure,
            room_label="SYN-RM3",
            total_price="3200",
        )
    )
    room_items.append(
        _room_item(
            1,
            group_code="SYN-FR-0731",
            parse_version_id=7401,
            segment_no=1,
            arrival=fr_arrival,
            departure=fr_departure,
            room_type="SYN-SUP-TRP-BF",
            quantity=1,
        )
    )

    ht_arrival = date(2026, 7, 29)
    ht_departure = date(2026, 7, 31)
    for record_id in (501, 502):
        facts.append(
            _fact(
                record_id,
                business_date=date(2026, 7, 29),
                daily_version_id=1029,
                company_key="HANA TOUR",
                channel_key="SYN-CHANNEL-HT",
                group_code="SYN-HT-0731",
                block_code="SYN-BLOCK-HT-A",
                arrival=ht_arrival,
                departure=ht_departure,
                room_label="SYN-RM2",
                total_price="1200",
            )
        )
    room_items.append(
        _room_item(
            1,
            group_code="SYN-HT-0731",
            parse_version_id=7501,
            segment_no=1,
            arrival=ht_arrival,
            departure=ht_departure,
            room_type="SYN-SUP-TWN-BF",
            quantity=2,
        )
    )

    versions_by_date: Dict[date, int] = {}
    for fact in facts:
        existing = versions_by_date.get(fact.business_date)
        if existing is not None and existing != fact.daily_version_id:
            raise AssertionError("synthetic date has conflicting daily versions")
        versions_by_date[fact.business_date] = fact.daily_version_id

    return BatchSnapshot(
        facts=tuple(facts),
        room_items=tuple(room_items),
        daily_versions=tuple(
            DailyVersionPin(business_date, version_id)
            for business_date, version_id in sorted(versions_by_date.items())
        ),
        group_parse_versions={
            "SYN-LT-0710": 7101,
            "SYN-QBD-REPEAT": 7201,
            "SYN-DY-0720": 7301,
            "SYN-FR-0731": 7401,
            "SYN-HT-0731": 7501,
        },
    )
