-- 创建公共站内通知事实表；不建立外键，接收人与资源引用由应用层显式校验。
CREATE TABLE tb_notification (
    id bigserial PRIMARY KEY,
    event_id varchar(64) NOT NULL,
    recipient_kind varchar(32) NOT NULL,
    recipient_id bigint NOT NULL,
    category varchar(32) NOT NULL,
    type varchar(100) NOT NULL,
    severity varchar(16) NOT NULL,
    title varchar(200) NOT NULL,
    body text NOT NULL,
    ref_type varchar(64) NOT NULL DEFAULT '',
    ref_id varchar(128) NOT NULL DEFAULT '',
    ref_key varchar(128) NOT NULL DEFAULT '',
    is_read boolean NOT NULL DEFAULT FALSE,
    read_at timestamptz,
    expires_at timestamptz,
    created_at timestamptz NOT NULL DEFAULT NOW(),
    CONSTRAINT uq_notification_event_recipient UNIQUE (event_id, recipient_kind, recipient_id),
    CONSTRAINT ck_notification_recipient_kind CHECK (recipient_kind IN ('account', 'personal_customer')),
    CONSTRAINT ck_notification_recipient_id CHECK (recipient_id > 0),
    CONSTRAINT ck_notification_required_text CHECK (event_id <> '' AND type <> '' AND title <> '' AND body <> ''),
    CONSTRAINT ck_notification_reference CHECK (
        (ref_type = '' AND ref_id = '' AND ref_key = '') OR
        (ref_type <> '' AND (ref_id <> '' OR ref_key <> ''))
    ),
    CONSTRAINT ck_notification_category CHECK (category IN ('approval', 'expiry', 'sync', 'system')),
    CONSTRAINT ck_notification_severity CHECK (severity IN ('info', 'warning', 'error', 'critical')),
    CONSTRAINT ck_notification_read_time CHECK ((is_read = FALSE AND read_at IS NULL) OR (is_read = TRUE AND read_at IS NOT NULL))
);

CREATE INDEX idx_notification_recipient_unread
    ON tb_notification (recipient_kind, recipient_id, is_read, created_at DESC, id DESC);
CREATE INDEX idx_notification_recipient_category
    ON tb_notification (recipient_kind, recipient_id, category, created_at DESC, id DESC);
CREATE INDEX idx_notification_expires_at
    ON tb_notification (expires_at, id) WHERE expires_at IS NOT NULL;

COMMENT ON TABLE tb_notification IS '公共站内通知事实';
COMMENT ON COLUMN tb_notification.id IS '通知主键ID';
COMMENT ON COLUMN tb_notification.event_id IS '上游稳定事件ID，与接收人共同防重';
COMMENT ON COLUMN tb_notification.recipient_kind IS '接收人类型：account后台账号，personal_customer个人客户';
COMMENT ON COLUMN tb_notification.recipient_id IS '接收人账号或个人客户ID';
COMMENT ON COLUMN tb_notification.category IS '通知分类：审批、临期、同步或系统';
COMMENT ON COLUMN tb_notification.type IS '稳定通知类型编码';
COMMENT ON COLUMN tb_notification.severity IS '通知严重级别：普通、警告、错误或严重';
COMMENT ON COLUMN tb_notification.title IS '发送时固化的纯文本标题';
COMMENT ON COLUMN tb_notification.body IS '发送时固化的纯文本正文';
COMMENT ON COLUMN tb_notification.ref_type IS '受控关联资源类型，空字符串表示无关联资源';
COMMENT ON COLUMN tb_notification.ref_id IS '受控关联资源ID，禁止保存任意URL';
COMMENT ON COLUMN tb_notification.ref_key IS '受控关联资源稳定键，禁止保存任意URL';
COMMENT ON COLUMN tb_notification.is_read IS '是否已被接收人读取';
COMMENT ON COLUMN tb_notification.read_at IS '接收人首次读取时间';
COMMENT ON COLUMN tb_notification.expires_at IS '通知停止展示时间，空值表示不自动过期';
COMMENT ON COLUMN tb_notification.created_at IS '通知创建时间';
