from __future__ import annotations

import unittest

from arr_web.repository import (
    DAILY_DOWNLOAD_SQL,
    JOBS_COUNT_SQL,
    JOBS_SQL,
    JOB_TRACE_ATTEMPTS_SQL,
    JOB_TRACE_DELIVERIES_SQL,
    JOB_TRACE_OUTBOX_SQL,
    JOB_TRACE_REVIEW_CASE_SQL,
    JOB_TRACE_REVIEW_EVENTS_SQL,
    JOB_TRACE_RUN_SQL,
    JOB_TRACE_SUBMISSIONS_SQL,
    JOB_TRACE_VERSIONS_SQL,
    HISTORY_MONTH_COUNTS_SQL,
    MONTHLY_DOWNLOAD_SQL,
    MONTHLY_RUNS_COUNT_SQL,
    MONTHLY_RUNS_SQL,
)


class PortalRepositorySchemaTests(unittest.TestCase):
    def test_queries_use_arr_mvp_v1_relations(self) -> None:
        sql = " ".join(
            (
                JOBS_SQL,
                JOBS_COUNT_SQL,
                DAILY_DOWNLOAD_SQL,
                MONTHLY_DOWNLOAD_SQL,
                MONTHLY_RUNS_SQL,
                MONTHLY_RUNS_COUNT_SQL,
                JOB_TRACE_RUN_SQL,
                JOB_TRACE_ATTEMPTS_SQL,
                JOB_TRACE_DELIVERIES_SQL,
                JOB_TRACE_SUBMISSIONS_SQL,
                JOB_TRACE_VERSIONS_SQL,
                JOB_TRACE_OUTBOX_SQL,
                JOB_TRACE_REVIEW_CASE_SQL,
                JOB_TRACE_REVIEW_EVENTS_SQL,
                HISTORY_MONTH_COUNTS_SQL,
            )
        )
        for required in (
            "ingestion.processing_runs",
            "ingestion.artifacts",
            "finance.daily_versions",
            "ingestion.daily_review_cases",
            "ingestion.daily_review_events",
            "reporting.monthly_runs",
        ):
            with self.subTest(required=required):
                self.assertIn(required, sql)

        for removed in (
            "finance.processing_jobs",
            "booking.file_objects",
            "finance.report_versions",
            "finance.report_channel_manifest",
        ):
            with self.subTest(removed=removed):
                self.assertNotIn(removed, sql)

    def test_history_queries_count_and_page_in_the_same_repository_contract(self) -> None:
        self.assertIn("count(*)", JOBS_COUNT_SQL.lower())
        self.assertIn("count(*)", MONTHLY_RUNS_COUNT_SQL.lower())
        self.assertIn("limit %s offset %s", JOBS_SQL.lower())
        self.assertIn("limit %s offset %s", MONTHLY_RUNS_SQL.lower())
        self.assertIn("run.as_of_date AS max_arrival_date", MONTHLY_RUNS_SQL)
        self.assertIn("full outer join monthly", HISTORY_MONTH_COUNTS_SQL.lower())
        self.assertIn("run.business_date", HISTORY_MONTH_COUNTS_SQL.lower())
        self.assertIn("asia/bangkok", HISTORY_MONTH_COUNTS_SQL.lower())
        self.assertIn("reporting.monthly_runs", HISTORY_MONTH_COUNTS_SQL.lower())

    def test_job_trace_queries_expose_only_diagnostic_columns(self) -> None:
        trace_sql = " ".join(
            (
                JOB_TRACE_RUN_SQL,
                JOB_TRACE_ATTEMPTS_SQL,
                JOB_TRACE_DELIVERIES_SQL,
                JOB_TRACE_SUBMISSIONS_SQL,
                JOB_TRACE_VERSIONS_SQL,
                JOB_TRACE_OUTBOX_SQL,
            )
        ).lower()
        for required in (
            "ingestion.processing_attempts",
            "ingestion.processing_deliveries",
            "ingestion.result_submissions",
            "ingestion.outbox_events",
            "finance.daily_versions",
        ):
            self.assertIn(required, trace_sql)
        for private_column in (
            "object_key",
            "delivery_json",
            "envelope_json",
            "payload_json",
            "receipt_json",
            "grant_sha256",
            "full_name",
            "res_comment",
            "trace_text",
        ):
            self.assertNotIn(private_column, trace_sql)

    def test_job_history_and_trace_are_limited_to_daily_processing_runs(self) -> None:
        daily_pipeline_filter = "run.pipeline_type = 'opera_daily'"
        self.assertIn(daily_pipeline_filter, JOBS_SQL)
        self.assertIn(daily_pipeline_filter, JOBS_COUNT_SQL)
        self.assertIn(daily_pipeline_filter, JOB_TRACE_RUN_SQL)

    def test_daily_filename_uses_uploaded_provenance_not_internal_artifact_name(self) -> None:
        self.assertIn("run.uploaded_filename", JOBS_SQL)
        self.assertIn("run.uploaded_filename", JOB_TRACE_RUN_SQL)
        self.assertNotIn("source.original_filename", JOBS_SQL)
        self.assertNotIn("source.original_filename", JOB_TRACE_RUN_SQL)


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