BEGIN;

-- Bootstrap FIFO v2 core tables before seed migration (20260218090010).
-- Keep definitions aligned with 20260304033546_create_fifo_stock_v2_core.

CREATE TABLE IF NOT EXISTS fifo_stock_v2_flag_groups (
    code VARCHAR(64) PRIMARY KEY,
    name VARCHAR(128) NOT NULL,
    priority INT NOT NULL DEFAULT 100,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_flag_members (
    flag_name VARCHAR(64) PRIMARY KEY,
    flag_group_code VARCHAR(64) NOT NULL REFERENCES fifo_stock_v2_flag_groups(code),
    priority INT NOT NULL DEFAULT 100,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_traits (
    id BIGSERIAL PRIMARY KEY,
    source_table VARCHAR(64) NOT NULL,
    lane VARCHAR(16) NOT NULL CHECK (lane IN ('STOCKABLE', 'USABLE')),
    date_table VARCHAR(64) NULL,
    date_join_left_col VARCHAR(64) NULL,
    date_join_right_col VARCHAR(64) NULL,
    date_column VARCHAR(64) NOT NULL,
    fallback_date_column VARCHAR(64) NULL,
    sort_priority INT NOT NULL DEFAULT 100,
    id_column VARCHAR(64) NOT NULL DEFAULT 'id',
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    UNIQUE (source_table, lane)
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_route_rules (
    id BIGSERIAL PRIMARY KEY,
    flag_group_code VARCHAR(64) NOT NULL REFERENCES fifo_stock_v2_flag_groups(code),
    lane VARCHAR(16) NOT NULL CHECK (lane IN ('STOCKABLE', 'USABLE')),
    function_code VARCHAR(64) NOT NULL,
    source_table VARCHAR(64) NOT NULL,
    source_id_column VARCHAR(64) NOT NULL DEFAULT 'id',
    product_warehouse_col VARCHAR(64) NOT NULL,
    quantity_col VARCHAR(64) NOT NULL,
    used_quantity_col VARCHAR(64) NULL,
    pending_quantity_col VARCHAR(64) NULL,
    scope_sql TEXT NULL,
    legacy_type_key VARCHAR(100) NOT NULL,
    allow_pending_default BOOLEAN NOT NULL DEFAULT TRUE,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (flag_group_code, lane, function_code, source_table)
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_overconsume_rules (
    id BIGSERIAL PRIMARY KEY,
    flag_group_code VARCHAR(64) NULL REFERENCES fifo_stock_v2_flag_groups(code),
    function_code VARCHAR(64) NULL,
    lane VARCHAR(16) NOT NULL DEFAULT 'USABLE' CHECK (lane IN ('STOCKABLE', 'USABLE')),
    allow_overconsume BOOLEAN NOT NULL,
    priority INT NOT NULL DEFAULT 100,
    reason TEXT NULL,
    is_active BOOLEAN NOT NULL DEFAULT TRUE
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_operation_log (
    id BIGSERIAL PRIMARY KEY,
    idempotency_key VARCHAR(128) NOT NULL,
    operation VARCHAR(16) NOT NULL CHECK (operation IN ('ALLOCATE', 'ROLLBACK', 'REFLOW', 'RECALCULATE')),
    product_warehouse_id BIGINT NOT NULL,
    flag_group_code VARCHAR(64) NOT NULL,
    usable_type VARCHAR(100) NULL,
    usable_id BIGINT NULL,
    request_hash VARCHAR(64) NOT NULL,
    status VARCHAR(16) NOT NULL CHECK (status IN ('RUNNING', 'DONE', 'FAILED')),
    result_payload JSONB NULL,
    error_text TEXT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    finished_at TIMESTAMPTZ NULL,
    UNIQUE (idempotency_key, operation)
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_reflow_runs (
    id BIGSERIAL PRIMARY KEY,
    mode VARCHAR(16) NOT NULL CHECK (mode IN ('DRY_RUN', 'APPLY')),
    status VARCHAR(16) NOT NULL CHECK (status IN ('RUNNING', 'PAUSED', 'DONE', 'FAILED', 'CANCELLED')),
    as_of TIMESTAMPTZ NULL,
    started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    finished_at TIMESTAMPTZ NULL,
    total_shards INT NOT NULL DEFAULT 0,
    processed_shards INT NOT NULL DEFAULT 0,
    processed_rows BIGINT NOT NULL DEFAULT 0,
    mismatch_rows BIGINT NOT NULL DEFAULT 0,
    created_by BIGINT NULL,
    note TEXT NULL
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_reflow_checkpoints (
    id BIGSERIAL PRIMARY KEY,
    run_id BIGINT NOT NULL REFERENCES fifo_stock_v2_reflow_runs(id) ON DELETE CASCADE,
    flag_group_code VARCHAR(64) NOT NULL,
    product_warehouse_id BIGINT NOT NULL,
    last_sort_at TIMESTAMPTZ NULL,
    last_source_table VARCHAR(64) NULL,
    last_source_id BIGINT NULL,
    status VARCHAR(16) NOT NULL CHECK (status IN ('PENDING', 'RUNNING', 'DONE', 'FAILED')) DEFAULT 'PENDING',
    retry_count INT NOT NULL DEFAULT 0,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (run_id, flag_group_code, product_warehouse_id)
);

CREATE TABLE IF NOT EXISTS fifo_stock_v2_shadow_allocations (
    id BIGSERIAL PRIMARY KEY,
    run_id BIGINT NOT NULL REFERENCES fifo_stock_v2_reflow_runs(id) ON DELETE CASCADE,
    product_warehouse_id BIGINT NOT NULL,
    stockable_type VARCHAR(100) NOT NULL,
    stockable_id BIGINT NOT NULL,
    usable_type VARCHAR(100) NOT NULL,
    usable_id BIGINT NOT NULL,
    qty NUMERIC(15,3) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
    sort_at TIMESTAMPTZ NULL,
    source_table VARCHAR(64) NULL,
    source_id BIGINT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_fifo_v2_shadow_run_usable
    ON fifo_stock_v2_shadow_allocations(run_id, usable_type, usable_id);

CREATE INDEX IF NOT EXISTS idx_fifo_v2_shadow_run_stockable
    ON fifo_stock_v2_shadow_allocations(run_id, stockable_type, stockable_id);

ALTER TABLE stock_allocations
    ADD COLUMN IF NOT EXISTS engine_version VARCHAR(8) NOT NULL DEFAULT 'v1',
    ADD COLUMN IF NOT EXISTS flag_group_code VARCHAR(64) NULL,
    ADD COLUMN IF NOT EXISTS function_code VARCHAR(64) NULL,
    ADD COLUMN IF NOT EXISTS reflow_run_id BIGINT NULL,
    ADD COLUMN IF NOT EXISTS idempotency_key VARCHAR(128) NULL;

CREATE INDEX IF NOT EXISTS idx_stock_allocations_engine_version
    ON stock_allocations(engine_version);

CREATE INDEX IF NOT EXISTS idx_stock_allocations_flag_group
    ON stock_allocations(flag_group_code);

CREATE INDEX IF NOT EXISTS idx_stock_allocations_idempotency
    ON stock_allocations(idempotency_key);

COMMIT;
