-- 2026-05-01
-- 业务运行上下文与沙箱隔离。

BEGIN;

CREATE TABLE IF NOT EXISTS biz.site_runtime_context (
    site_id bigint PRIMARY KEY,
    mode character varying(20) NOT NULL DEFAULT 'live',
    sandbox_date date,
    sandbox_instance_id character varying(64),
    ai_mode character varying(20) NOT NULL DEFAULT 'live',
    status character varying(20) NOT NULL DEFAULT 'active',
    reason text,
    updated_by bigint,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT site_runtime_context_site_id_fkey
        FOREIGN KEY (site_id) REFERENCES biz.sites(site_id),
    CONSTRAINT site_runtime_context_mode_check
        CHECK (mode IN ('live', 'sandbox')),
    CONSTRAINT site_runtime_context_ai_mode_check
        CHECK (ai_mode IN ('live')),
    CONSTRAINT site_runtime_context_sandbox_check
        CHECK (
            (mode = 'live' AND sandbox_date IS NULL AND sandbox_instance_id IS NULL)
            OR
            (mode = 'sandbox' AND sandbox_date IS NOT NULL AND sandbox_instance_id IS NOT NULL)
        )
);

COMMENT ON TABLE biz.site_runtime_context IS '门店业务运行上下文：live 使用真实日期，sandbox 使用指定业务日期并按实例隔离写入。';
COMMENT ON COLUMN biz.site_runtime_context.mode IS '运行模式：live / sandbox。';
COMMENT ON COLUMN biz.site_runtime_context.sandbox_date IS 'sandbox 模式下系统假设的业务日期。';
COMMENT ON COLUMN biz.site_runtime_context.sandbox_instance_id IS 'sandbox 模式写入隔离实例 ID。';
COMMENT ON COLUMN biz.site_runtime_context.ai_mode IS 'AI 调用模式；当前固定 live，沙箱也真实调用 DashScope。';

ALTER TABLE biz.coach_tasks
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

ALTER TABLE biz.coach_task_transfer_log
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

ALTER TABLE biz.recall_events
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

ALTER TABLE biz.coach_task_history
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

ALTER TABLE biz.ai_cache
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

ALTER TABLE biz.ai_run_logs
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

ALTER TABLE biz.ai_trigger_jobs
    ADD COLUMN IF NOT EXISTS runtime_mode character varying(20) NOT NULL DEFAULT 'live',
    ADD COLUMN IF NOT EXISTS sandbox_instance_id character varying(64) NOT NULL DEFAULT 'live';

UPDATE biz.coach_tasks SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;
UPDATE biz.coach_task_transfer_log SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;
UPDATE biz.recall_events SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;
UPDATE biz.coach_task_history SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;
UPDATE biz.ai_cache SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;
UPDATE biz.ai_run_logs SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;
UPDATE biz.ai_trigger_jobs SET runtime_mode = 'live', sandbox_instance_id = 'live' WHERE sandbox_instance_id IS NULL;

DROP INDEX IF EXISTS biz.idx_coach_tasks_site_assistant_member_type;
CREATE UNIQUE INDEX IF NOT EXISTS idx_coach_tasks_runtime_unique_active
    ON biz.coach_tasks (site_id, assistant_id, member_id, task_type, runtime_mode, sandbox_instance_id)
    WHERE status = 'active';

DROP INDEX IF EXISTS biz.idx_recall_events_site_assistant_member_day;
CREATE UNIQUE INDEX IF NOT EXISTS idx_recall_events_runtime_site_assistant_member_day
    ON biz.recall_events (
        site_id,
        assistant_id,
        member_id,
        runtime_mode,
        sandbox_instance_id,
        (date_trunc('day', pay_time AT TIME ZONE 'Asia/Shanghai'))
    );

CREATE INDEX IF NOT EXISTS idx_coach_tasks_runtime_assistant_status
    ON biz.coach_tasks (site_id, runtime_mode, sandbox_instance_id, assistant_id, status);

CREATE INDEX IF NOT EXISTS idx_ai_cache_runtime_lookup
    ON biz.ai_cache (cache_type, site_id, runtime_mode, sandbox_instance_id, target_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_ai_trigger_jobs_runtime_site
    ON biz.ai_trigger_jobs (site_id, runtime_mode, sandbox_instance_id, event_type, status);

COMMIT;

-- 回滚参考：
-- BEGIN;
-- DROP INDEX IF EXISTS biz.idx_ai_trigger_jobs_runtime_site;
-- DROP INDEX IF EXISTS biz.idx_ai_cache_runtime_lookup;
-- DROP INDEX IF EXISTS biz.idx_coach_tasks_runtime_assistant_status;
-- DROP INDEX IF EXISTS biz.idx_recall_events_runtime_site_assistant_member_day;
-- CREATE UNIQUE INDEX idx_recall_events_site_assistant_member_day ON biz.recall_events USING btree (site_id, assistant_id, member_id, (date_trunc('day', pay_time AT TIME ZONE 'Asia/Shanghai')));
-- DROP INDEX IF EXISTS biz.idx_coach_tasks_runtime_unique_active;
-- CREATE UNIQUE INDEX idx_coach_tasks_site_assistant_member_type ON biz.coach_tasks USING btree (site_id, assistant_id, member_id, task_type) WHERE status = 'active';
-- ALTER TABLE biz.ai_trigger_jobs DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- ALTER TABLE biz.ai_run_logs DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- ALTER TABLE biz.ai_cache DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- ALTER TABLE biz.coach_task_history DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- ALTER TABLE biz.recall_events DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- ALTER TABLE biz.coach_task_transfer_log DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- ALTER TABLE biz.coach_tasks DROP COLUMN IF EXISTS sandbox_instance_id, DROP COLUMN IF EXISTS runtime_mode;
-- DROP TABLE IF EXISTS biz.site_runtime_context;
-- COMMIT;
