-- 创建渠道无关通用审批实例；渠道模板、节点、审批人和外部凭据由 Adapter 自行管理。
CREATE TABLE tb_approval_instance (
    id bigserial PRIMARY KEY,
    business_type varchar(64) NOT NULL,
    business_id bigint NOT NULL,
    submitter_account_id bigint NOT NULL,
    submitter_snapshot jsonb NOT NULL,
    provider varchar(32) NOT NULL,
    external_ref varchar(128) NOT NULL DEFAULT '',
    status integer NOT NULL DEFAULT 0,
    request_snapshot jsonb NOT NULL,
    decision_snapshot jsonb,
    correlation_id varchar(100) NOT NULL,
    version integer NOT NULL DEFAULT 1,
    status_changed_at timestamptz NOT NULL DEFAULT NOW(),
    created_at timestamptz NOT NULL DEFAULT NOW(),
    updated_at timestamptz NOT NULL DEFAULT NOW(),
    CONSTRAINT uq_approval_instance_business UNIQUE (business_type, business_id),
    CONSTRAINT ck_approval_instance_business CHECK (business_type <> '' AND business_id > 0),
    CONSTRAINT ck_approval_instance_submitter CHECK (submitter_account_id > 0 AND jsonb_typeof(submitter_snapshot) = 'object'),
    CONSTRAINT ck_approval_instance_provider CHECK (provider <> ''),
    CONSTRAINT ck_approval_instance_status CHECK (status IN (0, 1, 2, 3, 4, 5, 6, 7, 8)),
    CONSTRAINT ck_approval_instance_request_snapshot CHECK (jsonb_typeof(request_snapshot) = 'object'),
    CONSTRAINT ck_approval_instance_decision_snapshot CHECK (decision_snapshot IS NULL OR jsonb_typeof(decision_snapshot) = 'object'),
    CONSTRAINT ck_approval_instance_correlation CHECK (correlation_id <> ''),
    CONSTRAINT ck_approval_instance_version CHECK (version > 0)
);

CREATE UNIQUE INDEX uq_approval_instance_external_ref
    ON tb_approval_instance (provider, external_ref) WHERE external_ref <> '';
CREATE INDEX idx_approval_instance_status_changed
    ON tb_approval_instance (status, status_changed_at, id);
CREATE INDEX idx_approval_instance_submitter
    ON tb_approval_instance (submitter_account_id, created_at DESC, id DESC);
CREATE INDEX idx_approval_instance_correlation
    ON tb_approval_instance (correlation_id);

-- 标准决策投递单独保存处理租约，使通过后撤销可在已通过之后再次幂等交给业务消费者。
CREATE TABLE tb_approval_decision_delivery (
    id bigserial PRIMARY KEY,
    instance_id bigint NOT NULL,
    decision varchar(32) NOT NULL,
    event_id varchar(64) NOT NULL,
    status integer NOT NULL DEFAULT 0,
    retry_count integer NOT NULL DEFAULT 0,
    lease_owner varchar(100),
    lease_expires_at timestamptz,
    last_error varchar(500) NOT NULL DEFAULT '',
    processed_at timestamptz,
    created_at timestamptz NOT NULL DEFAULT NOW(),
    updated_at timestamptz NOT NULL DEFAULT NOW(),
    CONSTRAINT uq_approval_decision_delivery UNIQUE (instance_id, decision),
    CONSTRAINT uq_approval_decision_delivery_event UNIQUE (event_id),
    CONSTRAINT ck_approval_decision_delivery_instance CHECK (instance_id > 0),
    CONSTRAINT ck_approval_decision_delivery_decision CHECK (decision IN ('approved', 'rejected', 'cancelled', 'deleted', 'revoked_after_approved')),
    CONSTRAINT ck_approval_decision_delivery_status CHECK (status IN (0, 1, 2, 3)),
    CONSTRAINT ck_approval_decision_delivery_retry CHECK (retry_count >= 0),
    CONSTRAINT ck_approval_decision_delivery_lease CHECK (
        (status = 1 AND lease_owner IS NOT NULL AND lease_expires_at IS NOT NULL) OR
        (status <> 1 AND lease_owner IS NULL AND lease_expires_at IS NULL)
    ),
    CONSTRAINT ck_approval_decision_delivery_processed CHECK (
        (status = 2 AND processed_at IS NOT NULL) OR
        (status <> 2 AND processed_at IS NULL)
    )
);

CREATE INDEX idx_approval_decision_delivery_claim
    ON tb_approval_decision_delivery (status, lease_expires_at, id);

COMMENT ON TABLE tb_approval_instance IS '渠道无关通用审批实例';
COMMENT ON COLUMN tb_approval_instance.id IS '通用审批实例主键ID';
COMMENT ON COLUMN tb_approval_instance.business_type IS '稳定业务类型编码';
COMMENT ON COLUMN tb_approval_instance.business_id IS '业务单主键ID，与业务类型共同唯一';
COMMENT ON COLUMN tb_approval_instance.submitter_account_id IS '真实业务提交人账号ID';
COMMENT ON COLUMN tb_approval_instance.submitter_snapshot IS '真实业务提交人名称、角色和归属快照';
COMMENT ON COLUMN tb_approval_instance.provider IS '审批渠道稳定编码，不包含渠道密钥或模板信息';
COMMENT ON COLUMN tb_approval_instance.external_ref IS '渠道返回的通用外部实例引用';
COMMENT ON COLUMN tb_approval_instance.status IS '通用审批生命周期状态：0提交中，1审批中，2已通过，3已拒绝，4已撤销，5通过后撤销，6已删除，7提交失败，8提交结果未知';
COMMENT ON COLUMN tb_approval_instance.request_snapshot IS '业务申请时冻结的渠道无关请求快照';
COMMENT ON COLUMN tb_approval_instance.decision_snapshot IS '首次标准终态时冻结的渠道无关决策快照';
COMMENT ON COLUMN tb_approval_instance.correlation_id IS '贯穿业务申请、渠道交互和异步处理的关联ID';
COMMENT ON COLUMN tb_approval_instance.version IS '通用审批实例乐观锁版本';
COMMENT ON COLUMN tb_approval_instance.status_changed_at IS '通用审批状态最近变化时间';
COMMENT ON COLUMN tb_approval_instance.created_at IS '通用审批实例创建时间';
COMMENT ON COLUMN tb_approval_instance.updated_at IS '通用审批实例更新时间';

COMMENT ON TABLE tb_approval_decision_delivery IS '通用审批标准决策业务投递事实';
COMMENT ON COLUMN tb_approval_decision_delivery.id IS '决策投递主键ID';
COMMENT ON COLUMN tb_approval_decision_delivery.instance_id IS '通用审批实例ID，通过代码显式维护关联';
COMMENT ON COLUMN tb_approval_decision_delivery.decision IS '渠道无关标准决策';
COMMENT ON COLUMN tb_approval_decision_delivery.event_id IS '对应公共Outbox的稳定事件ID';
COMMENT ON COLUMN tb_approval_decision_delivery.status IS '业务消费状态：0待处理，1处理中，2成功，3失败';
COMMENT ON COLUMN tb_approval_decision_delivery.retry_count IS '业务消费失败重试次数';
COMMENT ON COLUMN tb_approval_decision_delivery.lease_owner IS '当前业务消费者租约持有者';
COMMENT ON COLUMN tb_approval_decision_delivery.lease_expires_at IS '当前业务消费者租约过期时间';
COMMENT ON COLUMN tb_approval_decision_delivery.last_error IS '最近一次业务消费失败的安全摘要';
COMMENT ON COLUMN tb_approval_decision_delivery.processed_at IS '业务消费者幂等处理成功时间';
COMMENT ON COLUMN tb_approval_decision_delivery.created_at IS '决策投递创建时间';
COMMENT ON COLUMN tb_approval_decision_delivery.updated_at IS '决策投递更新时间';
