from __future__ import annotations

from pathlib import Path
import unittest


PROJECT_ROOT = Path(__file__).resolve().parents[1]
UP_PATH = PROJECT_ROOT / "database" / "017_daily_price_review.sql"
DOWN_PATH = PROJECT_ROOT / "database" / "017_daily_price_review.down.sql"


class DailyPriceReviewMigrationTests(unittest.TestCase):
    def test_forward_migration_adds_only_review_lifecycle_and_manual_lineage(self) -> None:
        sql = UP_PATH.read_text(encoding="utf-8")
        lowered = sql.lower()

        for required in (
            "current_database() <> 'booking_test'",
            "migrations 008 through 016 must be applied before 017",
            "CREATE TABLE ingestion.daily_review_cases",
            "CREATE TABLE ingestion.daily_review_items",
            "CREATE TABLE ingestion.daily_review_events",
            "processing_run_id bigint NOT NULL UNIQUE",
            "daily_review_items_key_unique",
            "'awaiting_review'",
            "'review_required'",
            "'recorded_review'",
            "numeric(18,2)",
            "'manual_review'",
            "manual_override_sha256",
            "manually_priced_rows",
            "daily_versions_source_rule_override_unique",
            "daily_review_items_mutability_guard",
            "daily_review_cases_immutability_guard",
            "daily_review_events_immutability_guard",
            "PRICE_REVIEW_REQUIRED",
            "PRICE_REVIEW_UPDATED",
            "PRICE_REVIEW_FINALIZED",
            "PRICE_REVIEW_CANCELLED",
            "PRICE_REVIEW_GENERATION_FAILED",
            "PRICE_REVIEW_FAILED",
            "result_delivery_mode = 'artifact_callback'",
            "result_delivery_mode = 'direct_mcp'",
        ):
            with self.subTest(required=required):
                self.assertIn(required, sql)

        review_section = lowered[
            lowered.index("create table ingestion.daily_review_cases") : lowered.index(
                "alter table finance.daily_versions"
            )
        ]
        for forbidden in ("full_name", "confirmation_no", "res_comment", "trace_text", "remarks"):
            with self.subTest(forbidden=forbidden):
                self.assertNotIn(forbidden, review_section)
        self.assertIn(
            "GRANT SELECT, INSERT, UPDATE ON ingestion.daily_review_cases, ingestion.daily_review_items TO arr_app",
            sql,
        )
        self.assertIn(
            "GRANT SELECT, INSERT ON ingestion.daily_review_events TO arr_app",
            sql,
        )
        self.assertNotIn("DROP SCHEMA", sql)

    def test_down_migration_refuses_to_discard_review_or_manual_facts(self) -> None:
        sql = DOWN_PATH.read_text(encoding="utf-8")
        for required in (
            "current_database() <> 'booking_test'",
            "SELECT 1 FROM ingestion.daily_review_cases",
            "review_case_id IS NOT NULL",
            "manual_override_sha256 IS NOT NULL",
            "run_status = 'awaiting_review'",
            "attempt_status = 'review_required'",
            "delivery_status = 'recorded_review'",
            "refusing destructive rollback: daily review or manual-pricing facts exist",
            "DROP TABLE ingestion.daily_review_events",
            "DROP TABLE ingestion.daily_review_items",
            "DROP TABLE ingestion.daily_review_cases",
            "daily_review_events_immutability_guard",
            "result_delivery_mode = 'artifact_callback'",
            "result_delivery_mode = 'direct_mcp'",
        ):
            with self.subTest(required=required):
                self.assertIn(required, sql)

    def test_followup_artifact_kind_migration_is_forward_only_after_manifest_facts(self) -> None:
        root = Path(__file__).resolve().parents[1]
        up = (root / "database" / "018_daily_review_manual_override_artifact.sql").read_text(
            encoding="utf-8"
        )
        down = (
            root / "database" / "018_daily_review_manual_override_artifact.down.sql"
        ).read_text(encoding="utf-8")

        self.assertIn("ARR migration 017 must be applied first", up)
        self.assertIn("'manual_override_json'", up)
        self.assertIn("artifacts_artifact_kind_check", up)
        self.assertIn("ARR migration 018 is already applied", up)
        self.assertIn("artifact_kind = 'manual_override_json'", down)
        self.assertIn("refusing rollback: immutable manual-override artifacts exist", down)


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