-- Deterministic monthly-report worksheet manifest
-- PostgreSQL 15+
-- Target database: booking_test (connect to that database before running).
-- Additive migration; do not edit applied migrations 001-005 in place.

BEGIN;

CREATE TABLE finance.report_channel_manifest (
    report_version_id bigint NOT NULL
        REFERENCES finance.report_versions(id),
    worksheet text NOT NULL CHECK (
        btrim(worksheet) <> ''
        AND char_length(worksheet) <= 31
    ),
    worksheet_order integer NOT NULL CHECK (worksheet_order > 0),
    row_count integer NOT NULL CHECK (row_count >= 0),
    PRIMARY KEY (report_version_id, worksheet),
    CONSTRAINT report_channel_manifest_order_unique
        UNIQUE (report_version_id, worksheet_order)
);

COMMENT ON TABLE finance.report_channel_manifest IS
  'Exact worksheet names, one-based order, and row counts for one immutable monthly-channel report artifact; empty worksheets are retained with row_count zero.';

CREATE OR REPLACE FUNCTION finance.validate_report_channel_manifest_parent()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM finance.report_versions AS report
        WHERE report.id = NEW.report_version_id
          AND report.report_kind = 'monthly_channel'
    ) THEN
        RAISE EXCEPTION
            'channel manifest must reference a monthly_channel report';
    END IF;
    RETURN NEW;
END;
$$;

CREATE TRIGGER report_channel_manifest_parent_guard
BEFORE INSERT OR UPDATE ON finance.report_channel_manifest
FOR EACH ROW
EXECUTE FUNCTION finance.validate_report_channel_manifest_parent();

-- Controlled backfill for the already-verified July 2026 monthly artifact in
-- booking_test. On a clean deployment this inserts zero rows. If another
-- current legacy monthly report exists, the guard below aborts the migration
-- so its sheet order can be inspected rather than guessed.
WITH verified_legacy_report AS (
    SELECT report.id
    FROM finance.report_versions AS report
    JOIN booking.file_objects AS artifact
      ON artifact.id = report.artifact_file_id
    WHERE report.report_kind = 'monthly_channel'
      AND report.period_start = DATE '2026-07-01'
      AND report.period_end = DATE '2026-07-31'
      AND report.as_of_date = DATE '2026-07-26'
      AND report.company_scope = '*'
      AND report.report_status = 'active'
      AND report.is_current
      AND artifact.file_kind = 'monthly_xlsx'
      AND artifact.sha256 =
          '592fee9b1e3e8290ed1e115d7eb213f09e780fa2bda08f6e270a34e7eaedd09f'
), manifest(worksheet, worksheet_order, row_count) AS (
    VALUES
        ('LIANTAI-GROUP', 1, 195),
        ('LIANTAI-FIT', 2, 275),
        ('QBD', 3, 258),
        ('DY-AI-Easy-KB', 4, 74),
        ('FENGRUN', 5, 41),
        ('T- HANATOUR TD CO., L', 6, 24)
)
INSERT INTO finance.report_channel_manifest (
    report_version_id, worksheet, worksheet_order, row_count
)
SELECT legacy.id, manifest.worksheet, manifest.worksheet_order, manifest.row_count
FROM verified_legacy_report AS legacy
CROSS JOIN manifest;

DO $$
BEGIN
    IF EXISTS (
        SELECT 1
        FROM finance.report_versions AS report
        WHERE report.report_kind = 'monthly_channel'
          AND report.report_status = 'active'
          AND report.is_current
          AND NOT EXISTS (
              SELECT 1
              FROM finance.report_channel_manifest AS manifest
              WHERE manifest.report_version_id = report.id
          )
    ) THEN
        RAISE EXCEPTION
            'current legacy monthly report requires an inspected channel manifest';
    END IF;
END;
$$;

CREATE OR REPLACE FUNCTION finance.protect_published_report_channel_manifest()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
    target_report_version_id bigint;
BEGIN
    target_report_version_id := CASE
        WHEN TG_OP = 'DELETE' THEN OLD.report_version_id
        ELSE NEW.report_version_id
    END;
    IF EXISTS (
        SELECT 1
        FROM finance.report_versions AS report
        WHERE report.id = target_report_version_id
          AND report.report_status IN ('active', 'superseded')
    ) THEN
        RAISE EXCEPTION
            'published monthly report channel manifest is immutable';
    END IF;
    RETURN CASE WHEN TG_OP = 'DELETE' THEN OLD ELSE NEW END;
END;
$$;

CREATE TRIGGER published_report_channel_manifest_guard
BEFORE INSERT OR UPDATE OR DELETE ON finance.report_channel_manifest
FOR EACH ROW
EXECUTE FUNCTION finance.protect_published_report_channel_manifest();

CREATE OR REPLACE FUNCTION finance.validate_monthly_report_channel_manifest()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
    manifest_count integer;
    first_order integer;
    last_order integer;
BEGIN
    IF NEW.report_kind = 'monthly_channel'
       AND NEW.report_status = 'active'
       AND NEW.is_current THEN
        SELECT count(*), min(worksheet_order), max(worksheet_order)
        INTO manifest_count, first_order, last_order
        FROM finance.report_channel_manifest
        WHERE report_version_id = NEW.id;

        IF manifest_count = 0
           OR first_order <> 1
           OR last_order <> manifest_count THEN
            RAISE EXCEPTION
                'active monthly report requires a continuous channel manifest';
        END IF;
    END IF;
    RETURN NEW;
END;
$$;

CREATE TRIGGER monthly_report_channel_manifest_guard
BEFORE INSERT OR UPDATE OF report_status, is_current
ON finance.report_versions
FOR EACH ROW
EXECUTE FUNCTION finance.validate_monthly_report_channel_manifest();

COMMIT;
