from __future__ import annotations

import hashlib
import json
import unittest
from pathlib import Path

from booking_ingestion.md_fixture import (
    build_fixture_parse_result,
    parse_fixture_markdown,
)


ROOT = Path(__file__).resolve().parents[1]
FIXTURE_PATH = (
    ROOT / "outputs" / "res_comment_20260727" /
    "RES_COMMENT_TYPE_OF_ROOM.md"
)
CONTRACT_PATH = (
    ROOT / "database" / "contracts" /
    "booking-row-parse-result.schema.json"
)


class BookingFixtureParserTests(unittest.TestCase):
    @unittest.skipUnless(
        FIXTURE_PATH.is_file(),
        "private booking acceptance fixture is not bundled with ARR2.0",
    )
    def test_real_fixture_preserves_every_source_row(self):
        document = parse_fixture_markdown(
            FIXTURE_PATH.read_text(encoding="utf-8")
        )
        self.assertEqual(len(document.rows), 867)
        self.assertEqual(document.worksheet_count, 6)
        self.assertEqual(document.distinct_group_code_count, 348)
        self.assertEqual(
            sum(row.no_of_rooms for row in document.rows),
            867,
        )
        repeated = len(document.rows) - document.distinct_group_code_count
        self.assertEqual(repeated, 519)
        coordinates = {
            (row.worksheet, row.row_no) for row in document.rows
        }
        self.assertEqual(len(coordinates), 867)

    @unittest.skipUnless(
        FIXTURE_PATH.is_file(),
        "private booking acceptance fixture is not bundled with ARR2.0",
    )
    def test_group_code_is_not_unique_or_merged(self):
        document = parse_fixture_markdown(
            FIXTURE_PATH.read_text(encoding="utf-8")
        )
        rows = [
            row for row in document.rows
            if row.group_code_key == "LT260718KB"
        ]
        self.assertEqual(len(rows), 12)
        self.assertEqual({row.type_of_room_raw for row in rows}, {"DBL"})
        self.assertEqual(sum(row.no_of_rooms for row in rows), 12)

    @unittest.skipUnless(
        FIXTURE_PATH.is_file(),
        "private booking acceptance fixture is not bundled with ARR2.0",
    )
    def test_simple_fixture_row_maps_to_one_room_item(self):
        document = parse_fixture_markdown(
            FIXTURE_PATH.read_text(encoding="utf-8")
        )
        rule_sha = hashlib.sha256(b"test-rule").hexdigest()
        result = build_fixture_parse_result(
            document.rows[0],
            rule_sha256=rule_sha,
        )
        self.assertEqual(result["status"], "accepted")
        self.assertEqual(result["no_of_rooms"], 1)
        self.assertEqual(len(result["room_items"]), 1)
        self.assertEqual(result["room_items"][0]["quantity"], 1)
        self.assertEqual(result["errors"], [])

    def test_contract_is_valid_json_and_declares_required_fields(self):
        schema = json.loads(CONTRACT_PATH.read_text(encoding="utf-8"))
        self.assertEqual(schema["$schema"], (
            "https://json-schema.org/draft/2020-12/schema"
        ))
        required = set(schema["required"])
        self.assertIn("source_row", required)
        self.assertIn("room_items", required)
        self.assertIn("no_of_rooms", required)

    def test_duplicate_source_coordinate_is_rejected(self):
        text = """
# GOURP_CODE、TYPE OF ROOM 与数量
来源文件：`source.xlsx`
房型映射文件：`mapping.xlsx`
## 工作表：SHEET
| 第 2 行 | G1 | DBL | 1 |
| 第 2 行 | G2 | TWN | 1 |
"""
        with self.assertRaisesRegex(ValueError, "duplicate"):
            parse_fixture_markdown(text)


if __name__ == "__main__":
    unittest.main()
