-- GWAS/QTL/MAS 闭环（对应规格 §8.22）5 张新表。
-- 全部幂等，可在已有 dev 库上重复执行。create_all 只建新表，本脚本显式补齐兜底。
-- 2026-08-04

-- ============ bre_gwas_result：GWAS 批次元数据 ============
CREATE TABLE IF NOT EXISTS bre_gwas_result (
    id                 integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    dataset_id         integer REFERENCES bre_genotyping_dataset(id) ON DELETE CASCADE,
    trait_id           integer REFERENCES bre_trait(id) ON DELETE CASCADE,
    trait_code         varchar(64),
    method             varchar(16),
    n_individuals      integer,
    n_markers          integer,
    m_after_maf        integer,
    maf_min            numeric,
    n_pc               integer,
    sig_level          numeric,
    threshold_bonf     numeric,
    n_sig_bonf         integer,
    n_sig_fdr          integer,
    n_qtl              integer,
    data_version       varchar(32),
    input_hash         varchar(64),
    engine_version     varchar(32),
    remark             varchar(512),
    created_time       timestamp with time zone NOT NULL DEFAULT now(),
    updated_time       timestamp with time zone,
    is_deleted         boolean NOT NULL DEFAULT false,
    deleted_time       timestamp with time zone,
    created_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    updated_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    deleted_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    uuid               varchar(64) NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_gwas_result_uuid ON bre_gwas_result (uuid);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_created_deleted ON bre_gwas_result (created_time, is_deleted);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_dataset_id ON bre_gwas_result (dataset_id);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_trait_id ON bre_gwas_result (trait_id);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_result_created_id ON bre_gwas_result (created_id);

-- ============ bre_gwas_snp：逐标记关联结果 ============
CREATE TABLE IF NOT EXISTS bre_gwas_snp (
    id                 integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    gwas_result_id     integer NOT NULL REFERENCES bre_gwas_result(id) ON DELETE CASCADE,
    marker_id          integer REFERENCES bre_marker(id) ON DELETE SET NULL,
    marker_name        varchar(64),
    chromosome         varchar(16),
    position           integer,
    maf                numeric,
    effect             numeric,
    se                 numeric,
    t_value            numeric,
    p_value            numeric,
    neg_log10p         numeric,
    q_value            numeric,
    sig_bonf           boolean,
    sig_fdr            boolean,
    created_time       timestamp with time zone NOT NULL DEFAULT now(),
    updated_time       timestamp with time zone,
    is_deleted         boolean NOT NULL DEFAULT false,
    deleted_time       timestamp with time zone,
    created_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    updated_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    deleted_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    uuid               varchar(64) NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_gwas_snp_uuid ON bre_gwas_snp (uuid);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_created_deleted ON bre_gwas_snp (created_time, is_deleted);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_gwas_result_id ON bre_gwas_snp (gwas_result_id);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_marker_id ON bre_gwas_snp (marker_id);
CREATE INDEX IF NOT EXISTS ix_bre_gwas_snp_created_id ON bre_gwas_snp (created_id);

-- ============ bre_qtl：QTL 区间（known 人工 / gwas 自动） ============
CREATE TABLE IF NOT EXISTS bre_qtl (
    id                 integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    trait_id           integer REFERENCES bre_trait(id) ON DELETE CASCADE,
    chromosome         varchar(16),
    start_bp           integer,
    end_bp             integer,
    peak_marker_id     integer REFERENCES bre_marker(id) ON DELETE SET NULL,
    peak_marker_name   varchar(64),
    peak_p             numeric,
    n_markers          integer,
    effect             numeric,
    source             varchar(8) DEFAULT 'known',
    gwas_result_id     integer REFERENCES bre_gwas_result(id) ON DELETE CASCADE,
    remark             varchar(512),
    created_time       timestamp with time zone NOT NULL DEFAULT now(),
    updated_time       timestamp with time zone,
    is_deleted         boolean NOT NULL DEFAULT false,
    deleted_time       timestamp with time zone,
    created_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    updated_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    deleted_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    uuid               varchar(64) NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_qtl_uuid ON bre_qtl (uuid);
CREATE INDEX IF NOT EXISTS ix_bre_qtl_created_deleted ON bre_qtl (created_time, is_deleted);
CREATE INDEX IF NOT EXISTS ix_bre_qtl_trait_id ON bre_qtl (trait_id);
CREATE INDEX IF NOT EXISTS ix_bre_qtl_peak_marker_id ON bre_qtl (peak_marker_id);
CREATE INDEX IF NOT EXISTS ix_bre_qtl_created_id ON bre_qtl (created_id);

-- ============ bre_mas_panel：MAS 标记辅助选择面板 ============
CREATE TABLE IF NOT EXISTS bre_mas_panel (
    id                 integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    panel_name         varchar(128),
    trait_id           integer REFERENCES bre_trait(id) ON DELETE CASCADE,
    n_markers          integer,
    remark             varchar(512),
    created_time       timestamp with time zone NOT NULL DEFAULT now(),
    updated_time       timestamp with time zone,
    is_deleted         boolean NOT NULL DEFAULT false,
    deleted_time       timestamp with time zone,
    created_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    updated_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    deleted_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    uuid               varchar(64) NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_mas_panel_uuid ON bre_mas_panel (uuid);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_created_deleted ON bre_mas_panel (created_time, is_deleted);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_trait_id ON bre_mas_panel (trait_id);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_created_id ON bre_mas_panel (created_id);

-- ============ bre_mas_panel_marker：面板标记（唯一 panel+marker） ============
CREATE TABLE IF NOT EXISTS bre_mas_panel_marker (
    id                 integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    panel_id           integer NOT NULL REFERENCES bre_mas_panel(id) ON DELETE CASCADE,
    marker_id          integer REFERENCES bre_marker(id) ON DELETE SET NULL,
    favorable_dose     integer,
    effect             numeric,
    direction          varchar(8) DEFAULT 'high',
    created_time       timestamp with time zone NOT NULL DEFAULT now(),
    updated_time       timestamp with time zone,
    is_deleted         boolean NOT NULL DEFAULT false,
    deleted_time       timestamp with time zone,
    created_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    updated_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    deleted_id         integer REFERENCES sys_user(id) ON UPDATE CASCADE ON DELETE SET NULL,
    uuid               varchar(64) NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_uuid ON bre_mas_panel_marker (uuid);
CREATE UNIQUE INDEX IF NOT EXISTS uq_bre_mas_panel_marker_panel_marker ON bre_mas_panel_marker (panel_id, marker_id);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_created_deleted ON bre_mas_panel_marker (created_time, is_deleted);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_panel_id ON bre_mas_panel_marker (panel_id);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_marker_id ON bre_mas_panel_marker (marker_id);
CREATE INDEX IF NOT EXISTS ix_bre_mas_panel_marker_created_id ON bre_mas_panel_marker (created_id);
