-- Protected rollback for migration 017. It deliberately refuses to discard any
-- review/audit/manual-price fact; use a forward corrective migration instead.

BEGIN;

DO $$
BEGIN
    IF current_database() <> 'booking_test' THEN
        RAISE EXCEPTION 'ARR daily price review rollback is allowed only in booking_test';
    END IF;
    IF to_regclass('ingestion.daily_review_cases') IS NULL THEN
        RAISE EXCEPTION 'ARR daily price review migration is not applied';
    END IF;
    IF EXISTS (SELECT 1 FROM ingestion.daily_review_cases)
       OR EXISTS (
            SELECT 1
            FROM finance.daily_versions
            WHERE review_case_id IS NOT NULL
               OR manual_override_sha256 IS NOT NULL
               OR manually_priced_rows <> 0
       )
       OR EXISTS (
            SELECT 1 FROM ingestion.processing_runs WHERE run_status = 'awaiting_review'
       )
       OR EXISTS (
            SELECT 1 FROM ingestion.processing_attempts WHERE attempt_status = 'review_required'
       )
       OR EXISTS (
            SELECT 1 FROM ingestion.processing_deliveries
            WHERE delivery_status = 'recorded_review' OR result_status = 'review_required'
       ) THEN
        RAISE EXCEPTION
            'refusing destructive rollback: daily review or manual-pricing facts exist';
    END IF;
END;
$$;

DO $$
BEGIN
    IF to_regrole('arr_app') IS NOT NULL THEN
        EXECUTE 'REVOKE SELECT, INSERT, UPDATE ON ingestion.daily_review_cases, ingestion.daily_review_items, ingestion.daily_review_events FROM arr_app';
        EXECUTE 'REVOKE USAGE, SELECT ON SEQUENCE ingestion.daily_review_cases_id_seq, ingestion.daily_review_items_id_seq, ingestion.daily_review_events_id_seq FROM arr_app';
    END IF;
END;
$$;

ALTER TABLE finance.daily_versions
    DROP CONSTRAINT IF EXISTS daily_versions_review_lineage_shape;
DROP INDEX IF EXISTS finance.daily_versions_review_case_unique;
DROP INDEX IF EXISTS finance.daily_versions_source_rule_override_unique;
ALTER TABLE finance.daily_versions
    DROP COLUMN manually_priced_rows,
    DROP COLUMN manual_override_sha256,
    DROP COLUMN review_case_id;

CREATE UNIQUE INDEX daily_versions_source_rule_unique
    ON finance.daily_versions (
        source_artifact_id,
        business_date,
        processor_version,
        rule_set_sha256
    )
    WHERE business_date IS NOT NULL;

ALTER TABLE finance.daily_records
    DROP CONSTRAINT IF EXISTS daily_records_retained_values;
ALTER TABLE finance.daily_records
    ADD CONSTRAINT daily_records_retained_values CHECK (
        outcome <> 'retained'
        OR (
            block_code IS NOT NULL
            AND adults IS NOT NULL AND adults >= 0
            AND children IS NOT NULL AND children >= 0
            AND company_name IS NOT NULL AND btrim(company_name) <> ''
            AND company_key IS NOT NULL AND btrim(company_key) <> ''
            AND confirmation_no IS NOT NULL AND btrim(confirmation_no) <> ''
            AND disp_room_no IS NOT NULL AND btrim(disp_room_no) <> ''
            AND effective_rate_amount IS NOT NULL AND effective_rate_amount >= 0
            AND full_name IS NOT NULL
            AND no_of_rooms IS NOT NULL AND no_of_rooms > 0
            AND rate_code IS NOT NULL
            AND normalized_rate_code IS NOT NULL
            AND arrival IS NOT NULL
            AND departure IS NOT NULL
            AND nights IS NOT NULL AND nights >= 0
            AND real_price IS NOT NULL AND real_price >= 0
            AND total_price IS NOT NULL AND total_price >= 0
            AND channel_key IS NOT NULL AND btrim(channel_key) <> ''
            AND pricing_method IN ('price_reference_exact', 'zero_price_exception')
        )
    );

ALTER TABLE ingestion.processing_deliveries
    DROP CONSTRAINT IF EXISTS processing_deliveries_review_case_fk,
    DROP COLUMN review_case_id,
    DROP COLUMN manual_override_artifact_id;

DROP TRIGGER IF EXISTS daily_review_items_mutability_guard ON ingestion.daily_review_items;
DROP TRIGGER IF EXISTS daily_review_cases_immutability_guard ON ingestion.daily_review_cases;
DROP TRIGGER IF EXISTS daily_review_events_immutability_guard ON ingestion.daily_review_events;
DROP FUNCTION IF EXISTS ingestion.enforce_daily_review_item_mutability();
DROP FUNCTION IF EXISTS ingestion.enforce_daily_review_case_immutability();
DROP FUNCTION IF EXISTS ingestion.enforce_daily_review_event_immutability();
DROP TABLE ingestion.daily_review_events;
DROP TABLE ingestion.daily_review_items;
DROP TABLE ingestion.daily_review_cases;

ALTER TABLE ingestion.processing_deliveries
    DROP CONSTRAINT IF EXISTS processing_deliveries_delivery_status_check,
    DROP CONSTRAINT IF EXISTS processing_deliveries_result_status_check;
ALTER TABLE ingestion.processing_deliveries
    ADD CONSTRAINT processing_deliveries_delivery_status_check CHECK (delivery_status IN (
        'received', 'validating', 'committed', 'recorded_failure', 'rejected'
    )),
    ADD CONSTRAINT processing_deliveries_result_status_check CHECK (result_status IN (
        'success', 'failed'
    ));

ALTER TABLE ingestion.processing_attempts
    DROP CONSTRAINT IF EXISTS processing_attempts_attempt_status_check,
    DROP CONSTRAINT IF EXISTS processing_attempts_terminal_shape;
ALTER TABLE ingestion.processing_attempts
    ADD CONSTRAINT processing_attempts_attempt_status_check CHECK (attempt_status IN (
        'queued', 'dispatched', 'running', 'delivered', 'succeeded', 'failed', 'cancelled'
    )),
    ADD CONSTRAINT processing_attempts_terminal_shape CHECK (
        (attempt_status = 'succeeded' AND failure_code IS NULL AND finished_at IS NOT NULL)
        OR (attempt_status = 'failed' AND failure_code IS NOT NULL AND finished_at IS NOT NULL)
        OR (attempt_status = 'cancelled' AND finished_at IS NOT NULL)
        OR attempt_status IN ('queued', 'dispatched', 'running', 'delivered')
    );

ALTER TABLE ingestion.processing_runs
    DROP CONSTRAINT IF EXISTS processing_runs_run_status_check,
    DROP CONSTRAINT IF EXISTS processing_runs_terminal_shape;
ALTER TABLE ingestion.processing_runs
    ADD CONSTRAINT processing_runs_run_status_check CHECK (run_status IN (
        'received', 'queued', 'running', 'validating', 'accepted', 'rejected', 'failed', 'cancelled'
    )),
    ADD CONSTRAINT processing_runs_terminal_shape CHECK (
        (
            run_status = 'accepted'
            AND failure_code IS NULL
            AND validated_at IS NOT NULL
            AND finished_at IS NOT NULL
            AND (
                pipeline_type <> 'opera_daily'
                OR (
                    business_date IS NOT NULL
                    AND delivered_processor_version IS NOT NULL
                    AND delivered_rule_set_sha256 IS NOT NULL
                    AND result_schema_version IS NOT NULL
                    AND delivery_sha256 IS NOT NULL
                    AND (
                        (
                            result_delivery_mode = 'artifact_callback'
                            AND result_artifact_id IS NOT NULL
                        )
                        OR (
                            result_delivery_mode = 'direct_mcp'
                            AND result_artifact_id IS NULL
                        )
                    )
                )
            )
        )
        OR (run_status IN ('rejected', 'failed') AND failure_code IS NOT NULL AND finished_at IS NOT NULL)
        OR (run_status = 'cancelled' AND finished_at IS NOT NULL)
        OR run_status IN ('received', 'queued', 'running', 'validating')
    );

COMMIT;
