-- Migration: Create Approval Queue table for model activation workflow
-- Purpose: Track models awaiting human approval after shadow run validation
-- PIT Safety: Immutable workflow records (append-only status transitions)

CREATE TABLE model_operations.approval_queue (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- References
    run_id UUID NOT NULL UNIQUE,
    model_id UUID NOT NULL,

    -- Workflow status
    status VARCHAR(32) NOT NULL DEFAULT 'Pending',  -- Pending, Approved, Rejected
    requested_by UUID,
    approved_by UUID,

    -- Approval details
    approval_reason TEXT,
    rejection_reason TEXT,

    -- Timestamps
    requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    approved_at TIMESTAMP,
    rejected_at TIMESTAMP,

    -- Constraints
    CONSTRAINT approval_queue_run_fk
        FOREIGN KEY (run_id) REFERENCES model_operations.shadow_run(run_id) ON DELETE RESTRICT,

    CONSTRAINT approval_queue_status_valid
        CHECK (status IN ('Pending', 'Approved', 'Rejected')),

    CONSTRAINT approval_queue_approval_check
        CHECK (
            (status = 'Approved' AND approved_by IS NOT NULL AND approved_at IS NOT NULL)
            OR (status != 'Approved')
        ),

    CONSTRAINT approval_queue_rejection_check
        CHECK (
            (status = 'Rejected' AND rejection_reason IS NOT NULL AND rejected_at IS NOT NULL)
            OR (status != 'Rejected')
        )
);

-- Indexes
CREATE INDEX approval_queue_status_idx ON model_operations.approval_queue(status);
CREATE INDEX approval_queue_model_idx ON model_operations.approval_queue(model_id, requested_at DESC);
CREATE INDEX approval_queue_requested_idx ON model_operations.approval_queue(requested_at DESC);

-- Trigger: Ensure approval_at is set only when status = 'Approved'
CREATE OR REPLACE FUNCTION model_operations.approval_queue_check()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.status = 'Approved' THEN
        IF NEW.approved_at IS NULL THEN
            NEW.approved_at := CURRENT_TIMESTAMP;
        END IF;
        IF NEW.approved_by IS NULL THEN
            RAISE EXCEPTION 'approved_by must be set when status = Approved';
        END IF;
    END IF;

    IF NEW.status = 'Rejected' THEN
        IF NEW.rejected_at IS NULL THEN
            NEW.rejected_at := CURRENT_TIMESTAMP;
        END IF;
        IF NEW.rejection_reason IS NULL THEN
            RAISE EXCEPTION 'rejection_reason must be set when status = Rejected';
        END IF;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER approval_queue_check_trigger
BEFORE INSERT OR UPDATE ON model_operations.approval_queue
FOR EACH ROW
EXECUTE FUNCTION model_operations.approval_queue_check();
