-- Durable Booking Excel extraction drafts and item-level human review.
-- PostgreSQL 15+. Migrations 008-014 remain immutable.

BEGIN;

DO $$
BEGIN
    IF current_database() <> 'booking_test' THEN
        RAISE EXCEPTION
            'ARR Booking review migration is allowed only in booking_test';
    END IF;
    IF to_regclass('booking.current_source_batch') IS NULL
       OR to_regclass('booking.room_items') IS NULL
       OR to_regclass('ingestion.artifacts') IS NULL THEN
        RAISE EXCEPTION
            'ARR migrations 008 through 014 must be applied first';
    END IF;
    IF to_regclass('booking.extraction_drafts') IS NOT NULL
       OR to_regclass('booking.extraction_draft_items') IS NOT NULL THEN
        RAISE EXCEPTION
            'ARR Booking review migration is already applied';
    END IF;
END;
$$;

CREATE TABLE booking.extraction_drafts (
    draft_id text PRIMARY KEY CHECK (
        draft_id ~ '^bookingdraft-[0-9a-f]{32}$'
    ),
    source_artifact_id bigint NOT NULL UNIQUE
        REFERENCES ingestion.artifacts(id),
    draft_status text NOT NULL CHECK (
        draft_status IN ('reviewing', 'activated', 'superseded')
    ),
    processor_version text NOT NULL CHECK (btrim(processor_version) <> ''),
    rule_set_sha256 character(64) NOT NULL CHECK (
        rule_set_sha256 ~ '^[0-9a-f]{64}$'
    ),
    source_sha256 character(64) NOT NULL CHECK (
        source_sha256 ~ '^[0-9a-f]{64}$'
    ),
    source_byte_size bigint NOT NULL CHECK (source_byte_size > 0),
    source_rows integer NOT NULL CHECK (source_rows > 0),
    worksheet_count integer NOT NULL CHECK (worksheet_count > 0),
    distinct_group_codes integer NOT NULL CHECK (distinct_group_codes > 0),
    extracted_items integer NOT NULL CHECK (extracted_items > 0),
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    activated_source_batch_id bigint UNIQUE
        REFERENCES booking.source_batches(id),
    activated_at timestamptz,
    CONSTRAINT extraction_drafts_status_shape CHECK (
        (
            draft_status = 'reviewing'
            AND activated_source_batch_id IS NULL
            AND activated_at IS NULL
        )
        OR (
            draft_status = 'activated'
            AND activated_source_batch_id IS NOT NULL
            AND activated_at IS NOT NULL
        )
        OR (
            draft_status = 'superseded'
            AND activated_source_batch_id IS NULL
            AND activated_at IS NULL
        )
    )
);

CREATE INDEX extraction_drafts_status_created_idx
    ON booking.extraction_drafts (draft_status, created_at DESC);

CREATE TABLE booking.extraction_draft_items (
    id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    draft_id text NOT NULL
        REFERENCES booking.extraction_drafts(draft_id),
    source_worksheet text NOT NULL CHECK (btrim(source_worksheet) <> ''),
    source_row_no integer NOT NULL CHECK (source_row_no > 0),
    item_no integer NOT NULL CHECK (item_no > 0),
    group_code_raw text NOT NULL CHECK (btrim(group_code_raw) <> ''),
    group_code_key text GENERATED ALWAYS AS (
        upper(btrim(group_code_raw))
    ) STORED,
    hotel_raw text NOT NULL CHECK (btrim(hotel_raw) <> ''),
    room_type_raw text NOT NULL CHECK (btrim(room_type_raw) <> ''),
    room_type_code text CHECK (
        room_type_code IS NULL OR btrim(room_type_code) <> ''
    ),
    quantity integer NOT NULL CHECK (quantity BETWEEN 1 AND 9999),
    review_status text NOT NULL CHECK (
        review_status IN ('confirmed', 'pending', 'deleted')
    ),
    automatic boolean NOT NULL,
    source_fragment text NOT NULL DEFAULT '',
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT extraction_draft_items_position_unique UNIQUE (
        draft_id,
        source_worksheet,
        source_row_no,
        item_no
    ),
    CONSTRAINT extraction_draft_items_review_shape CHECK (
        (review_status = 'confirmed' AND room_type_code IS NOT NULL)
        OR (review_status = 'pending' AND room_type_code IS NULL)
        OR review_status = 'deleted'
    )
);

CREATE INDEX extraction_draft_items_draft_status_idx
    ON booking.extraction_draft_items (draft_id, review_status, id);

CREATE INDEX extraction_draft_items_group_idx
    ON booking.extraction_draft_items (draft_id, group_code_key);

COMMENT ON TABLE booking.extraction_drafts IS
  'Private Booking Excel extraction drafts. A reviewing draft never changes the active accepted Booking source.';

COMMENT ON TABLE booking.extraction_draft_items IS
  'Editable extracted room items. Pending items are excluded until confirmed; deleted items remain audit-visible.';

COMMIT;
