-- =============================================================================
-- AwoooP Phase 7: Channel Hub 雙表
-- ADR-106（channel_event family）+ Progressive Feedback Policy
-- 2026-05-04 ogt + Claude Sonnet 4.6
-- =============================================================================
-- 兩張表：
--   awooop_conversation_event — 入站事件鏡像（Telegram/LINE inbound）
--   awooop_outbound_message   — 出站訊息記錄（interim + final reply）
-- =============================================================================

BEGIN;

-- ---------------------------------------------------------------------------
-- 1. awooop_conversation_event — 入站 Channel Event 鏡像
-- 目的：AwoooP 平台保留所有入站事件的不可變記錄，與 legacy 系統解耦
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS awooop_conversation_event (
    event_id         UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
    project_id       VARCHAR(64)  NOT NULL
        REFERENCES awooop_projects(project_id) ON DELETE CASCADE,
    -- Channel 原始身份
    channel_type     VARCHAR(32)  NOT NULL,    -- 'telegram' | 'line' | 'slack' | 'api'
    provider_event_id VARCHAR(256) NOT NULL,   -- Telegram: message_id, LINE: webhook event_id
    -- 統一身份（由 ProviderProxy 注入）
    platform_subject_id VARCHAR(128),
    channel_user_id  VARCHAR(256),
    channel_chat_id  VARCHAR(256),
    -- 關聯 run（若已建立）
    run_id           UUID,                     -- FK soft（run 可能晚於 event 建立）
    -- 事件內容（只存摘要/hash，不存明文）
    content_type     VARCHAR(32)  NOT NULL DEFAULT 'text',  -- 'text' | 'photo' | 'document' | 'command'
    content_hash     VARCHAR(64),              -- sha256(raw_content)，明文不入庫
    content_preview  VARCHAR(256),             -- 前 256 字元（無 PII/secret）
    attachment_sha256 VARCHAR(64),             -- 附件 sha256
    -- 去重（與 awooop_run_idempotency 對應）
    is_duplicate     BOOLEAN      NOT NULL DEFAULT FALSE,
    -- 時間
    provider_ts      TIMESTAMPTZ,              -- provider 原始時間戳
    received_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW(),

    CONSTRAINT chk_conv_event_channel_type
        CHECK (channel_type IN ('telegram','line','slack','api','internal')),
    CONSTRAINT chk_conv_event_content_type
        CHECK (content_type IN ('text','photo','document','command','callback_query')),
    CONSTRAINT uix_conv_event_dedup
        UNIQUE (project_id, channel_type, provider_event_id)
);

CREATE INDEX IF NOT EXISTS idx_conv_event_run
    ON awooop_conversation_event (project_id, run_id, received_at DESC);

CREATE INDEX IF NOT EXISTS idx_conv_event_subject
    ON awooop_conversation_event (project_id, platform_subject_id, received_at DESC);

CREATE INDEX IF NOT EXISTS idx_conv_event_recent
    ON awooop_conversation_event (project_id, channel_type, received_at DESC);

-- ---------------------------------------------------------------------------
-- 2. awooop_outbound_message — 出站訊息記錄（interim + final reply）
-- 目的：追蹤 AwoooP 發出的每一條訊息（shadow 不發、canary/active 發）
-- Progressive Feedback Policy：WAITING_TOOL 超過 30s → 發 interim message
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS awooop_outbound_message (
    message_id       UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
    project_id       VARCHAR(64)  NOT NULL
        REFERENCES awooop_projects(project_id) ON DELETE CASCADE,
    run_id           UUID         NOT NULL,   -- FK soft
    conversation_event_id UUID,               -- 觸發訊息的入站 event
    -- 出站目的地
    channel_type     VARCHAR(32)  NOT NULL,
    channel_chat_id  VARCHAR(256) NOT NULL,
    -- 訊息分類
    message_type     VARCHAR(32)  NOT NULL,   -- 'interim' | 'final' | 'error' | 'approval_request'
    -- 內容（只存 hash，不存明文）
    content_hash     VARCHAR(64),             -- sha256(rendered_content)
    content_preview  VARCHAR(256),            -- 前 256 字元（無 PII/secret）
    -- provider 回報的 message_id（Telegram: message.message_id）
    provider_message_id VARCHAR(64),
    -- 狀態
    send_status      VARCHAR(16)  NOT NULL DEFAULT 'pending',  -- 'pending'|'sent'|'failed'|'shadow'
    send_error       TEXT,
    -- 時間
    queued_at        TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
    sent_at          TIMESTAMPTZ,
    -- Progressive Feedback Policy（WAITING_TOOL 超 30s 觸發 interim）
    triggered_by_state VARCHAR(32),           -- 觸發本訊息的 run state（'waiting_tool'等）
    waiting_since    TIMESTAMPTZ,             -- 開始等待的時間（計算 30s 超時用）

    CONSTRAINT chk_outbound_channel_type
        CHECK (channel_type IN ('telegram','line','slack','api','internal')),
    CONSTRAINT chk_outbound_message_type
        CHECK (message_type IN ('interim','final','error','approval_request')),
    CONSTRAINT chk_outbound_send_status
        CHECK (send_status IN ('pending','sent','failed','shadow'))
);

CREATE INDEX IF NOT EXISTS idx_outbound_msg_run
    ON awooop_outbound_message (project_id, run_id, queued_at DESC);

CREATE INDEX IF NOT EXISTS idx_outbound_msg_pending
    ON awooop_outbound_message (project_id, channel_type, queued_at)
    WHERE send_status = 'pending';

-- Progressive Feedback Policy 查詢：找等待超過 30s 的 runs
CREATE INDEX IF NOT EXISTS idx_outbound_msg_waiting
    ON awooop_outbound_message (project_id, triggered_by_state, waiting_since)
    WHERE triggered_by_state = 'waiting_tool' AND send_status = 'pending';

-- =============================================================================
-- Row Level Security
-- =============================================================================

ALTER TABLE awooop_conversation_event ENABLE ROW LEVEL SECURITY;
ALTER TABLE awooop_outbound_message   ENABLE ROW LEVEL SECURITY;

ALTER TABLE awooop_conversation_event FORCE ROW LEVEL SECURITY;
ALTER TABLE awooop_outbound_message   FORCE ROW LEVEL SECURITY;

CREATE POLICY conv_event_tenant_isolation ON awooop_conversation_event
    USING (
        project_id = current_setting('app.project_id', TRUE)
        OR current_setting('app.project_id', TRUE) IS NULL
    );

CREATE POLICY outbound_msg_tenant_isolation ON awooop_outbound_message
    USING (
        project_id = current_setting('app.project_id', TRUE)
        OR current_setting('app.project_id', TRUE) IS NULL
    );

COMMIT;
