-- 009: IM Features — Discord/Slack-class messaging support
--
-- New tables:
--   user_presence, user_activity,
--   channel_category, channel_permission_overwrite, im_integration,
--   message_attachment, message_embed, message_draft, message_pin,
--   message_edit_history, saved_message, thread_read_state,
--   custom_emoji

-- ============================================================
-- 1. User Presence
-- ============================================================

-- models/users/user_presence.rs  →  user_presence
CREATE TABLE IF NOT EXISTS user_presence (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    status TEXT NOT NULL,
    custom_status_text TEXT NULL,
    custom_status_emoji TEXT NULL,
    device_type TEXT NULL,
    ip_address TEXT NULL,
    last_active_at TIMESTAMPTZ NOT NULL,
    last_seen_at TIMESTAMPTZ NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_user_presence_user_id UNIQUE (user_id)
);
CREATE INDEX IF NOT EXISTS idx_user_presence_status ON user_presence (status);

-- ============================================================
-- 2. User Activity (Rich Presence)
-- ============================================================

-- models/users/user_activity.rs  →  user_activity
CREATE TABLE IF NOT EXISTS user_activity (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    activity_type TEXT NOT NULL,
    name TEXT NOT NULL,
    details TEXT NULL,
    state TEXT NULL,
    application_id TEXT NULL,
    assets JSONB NULL,
    party_id TEXT NULL,
    party_current_size INTEGER NULL,
    party_max_size INTEGER NULL,
    large_image_url TEXT NULL,
    small_image_url TEXT NULL,
    start_at TIMESTAMPTZ NULL,
    end_at TIMESTAMPTZ NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_user_activity_user_id ON user_activity (user_id);

-- ============================================================
-- 3. Channel Categories
-- ============================================================

-- models/channels/channel_categories.rs  →  channel_category
CREATE TABLE IF NOT EXISTS channel_category (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE,
    name TEXT NOT NULL,
    position INTEGER NOT NULL,
    collapsed BOOLEAN NOT NULL,
    created_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_channel_category_workspace_id ON channel_category (workspace_id);

-- ============================================================
-- 4. ALTER channel — add category_id (after channel_category exists)
-- ============================================================

ALTER TABLE channel ADD COLUMN IF NOT EXISTS category_id UUID NULL REFERENCES channel_category(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS idx_channel_category_id ON channel (category_id);

-- ============================================================
-- 5. Channel Permission Overwrites
-- ============================================================

-- models/channels/channel_permission_overwrites.rs  →  channel_permission_overwrite
CREATE TABLE IF NOT EXISTS channel_permission_overwrite (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    target_type TEXT NOT NULL,
    target_id UUID NOT NULL,
    allow TEXT[] NOT NULL,
    deny TEXT[] NOT NULL,
    created_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_channel_perm_overwrite UNIQUE (channel_id, target_type, target_id)
);
CREATE INDEX IF NOT EXISTS idx_channel_perm_overwrite_channel_id ON channel_permission_overwrite (channel_id);
CREATE INDEX IF NOT EXISTS idx_channel_perm_overwrite_target ON channel_permission_overwrite (target_type, target_id);

-- ============================================================
-- 6. IM Integrations (External Bridge)
-- ============================================================

-- models/channels/im_integrations.rs  →  im_integration
CREATE TABLE IF NOT EXISTS im_integration (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE,
    provider TEXT NOT NULL,
    name TEXT NOT NULL,
    external_workspace_id TEXT NULL,
    internal_channel_id UUID NULL REFERENCES channel(id) ON DELETE SET NULL,
    external_channel_id TEXT NULL,
    bot_token_ciphertext TEXT NULL,
    webhook_url TEXT NULL,
    sync_direction TEXT NOT NULL,
    user_mapping JSONB NULL,
    enabled BOOLEAN NOT NULL,
    installed_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    last_sync_at TIMESTAMPTZ NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_im_integration_workspace_id ON im_integration (workspace_id);
CREATE INDEX IF NOT EXISTS idx_im_integration_internal_channel_id ON im_integration (internal_channel_id);
CREATE INDEX IF NOT EXISTS idx_im_integration_provider ON im_integration (provider);

-- ============================================================
-- 7. Message Attachments
-- ============================================================

-- models/channels/message_attachments.rs  →  message_attachment
CREATE TABLE IF NOT EXISTS message_attachment (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    message_id UUID NOT NULL REFERENCES message(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    filename TEXT NOT NULL,
    url TEXT NOT NULL,
    proxy_url TEXT NULL,
    size_bytes BIGINT NOT NULL,
    mime_type TEXT NOT NULL,
    width INTEGER NULL,
    height INTEGER NULL,
    duration_ms BIGINT NULL,
    thumbnail_url TEXT NULL,
    blurhash TEXT NULL,
    created_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_message_attachment_message_id ON message_attachment (message_id);
CREATE INDEX IF NOT EXISTS idx_message_attachment_channel_id ON message_attachment (channel_id);

-- ============================================================
-- 8. Message Embeds (Rich Text / Link Previews)
-- ============================================================

-- models/channels/message_embeds.rs  →  message_embed
CREATE TABLE IF NOT EXISTS message_embed (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    message_id UUID NOT NULL REFERENCES message(id) ON DELETE CASCADE,
    embed_type TEXT NOT NULL,
    title TEXT NULL,
    description TEXT NULL,
    url TEXT NULL,
    author_name TEXT NULL,
    author_url TEXT NULL,
    author_icon_url TEXT NULL,
    thumbnail_url TEXT NULL,
    thumbnail_width INTEGER NULL,
    thumbnail_height INTEGER NULL,
    image_url TEXT NULL,
    image_width INTEGER NULL,
    image_height INTEGER NULL,
    video_url TEXT NULL,
    video_width INTEGER NULL,
    video_height INTEGER NULL,
    color INTEGER NULL,
    fields JSONB NULL,
    footer_text TEXT NULL,
    footer_icon_url TEXT NULL,
    provider_name TEXT NULL,
    provider_url TEXT NULL,
    "timestamp" TIMESTAMPTZ NULL,
    created_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_message_embed_message_id ON message_embed (message_id);

-- ============================================================
-- 9. Message Drafts
-- ============================================================

-- models/channels/message_drafts.rs  →  message_draft
CREATE TABLE IF NOT EXISTS message_draft (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    thread_id UUID NULL,
    reply_to_message_id UUID NULL,
    content TEXT NOT NULL,
    attachments JSONB NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_message_draft_user_channel UNIQUE (user_id, channel_id)
);
CREATE INDEX IF NOT EXISTS idx_message_draft_user_id ON message_draft (user_id);
CREATE INDEX IF NOT EXISTS idx_message_draft_channel_id ON message_draft (channel_id);

-- ============================================================
-- 10. Custom Emojis
-- ============================================================

-- models/channels/custom_emojis.rs  →  custom_emoji
CREATE TABLE IF NOT EXISTS custom_emoji (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE,
    name TEXT NOT NULL,
    url TEXT NOT NULL,
    animated BOOLEAN NOT NULL,
    managed BOOLEAN NOT NULL,
    created_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_custom_emoji_workspace_name UNIQUE (workspace_id, name)
);
CREATE INDEX IF NOT EXISTS idx_custom_emoji_workspace_id ON custom_emoji (workspace_id);

-- ============================================================
-- 11. Message Pins
-- ============================================================

-- models/channels/message_pins.rs  →  message_pin
CREATE TABLE IF NOT EXISTS message_pin (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    message_id UUID NOT NULL REFERENCES message(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    pinned_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    pinned_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_message_pin_message_id UNIQUE (message_id)
);
CREATE INDEX IF NOT EXISTS idx_message_pin_channel_id ON message_pin (channel_id);
CREATE INDEX IF NOT EXISTS idx_message_pin_message_id ON message_pin (message_id);

-- ============================================================
-- 12. Message Edit History
-- ============================================================

-- models/channels/message_edit_history.rs  →  message_edit_history
CREATE TABLE IF NOT EXISTS message_edit_history (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    message_id UUID NOT NULL REFERENCES message(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    previous_body TEXT NOT NULL,
    edited_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    edited_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_message_edit_history_message_id ON message_edit_history (message_id);
CREATE INDEX IF NOT EXISTS idx_message_edit_history_channel_id ON message_edit_history (channel_id);

-- ============================================================
-- 13. Saved Messages
-- ============================================================

-- models/channels/saved_messages.rs  →  saved_message
CREATE TABLE IF NOT EXISTS saved_message (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    message_id UUID NOT NULL REFERENCES message(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    note TEXT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_saved_message_user_message UNIQUE (user_id, message_id)
);
CREATE INDEX IF NOT EXISTS idx_saved_message_user_id ON saved_message (user_id);
CREATE INDEX IF NOT EXISTS idx_saved_message_message_id ON saved_message (message_id);

-- ============================================================
-- 14. Thread Read States
-- ============================================================

-- models/channels/thread_read_states.rs  →  thread_read_state
CREATE TABLE IF NOT EXISTS thread_read_state (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    thread_id UUID NOT NULL,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    last_read_message_id UUID NULL,
    last_read_at TIMESTAMPTZ NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_thread_read_state_user_thread UNIQUE (user_id, thread_id)
);
CREATE INDEX IF NOT EXISTS idx_thread_read_state_user_id ON thread_read_state (user_id);
CREATE INDEX IF NOT EXISTS idx_thread_read_state_thread_id ON thread_read_state (thread_id);
CREATE INDEX IF NOT EXISTS idx_thread_read_state_channel_id ON thread_read_state (channel_id);

-- ============================================================
-- 15. Triggers — auto-refresh updated_at
-- ============================================================

DROP TRIGGER IF EXISTS trg_user_presence_updated_at ON user_presence;
CREATE TRIGGER trg_user_presence_updated_at BEFORE UPDATE ON user_presence FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_user_activity_updated_at ON user_activity;
CREATE TRIGGER trg_user_activity_updated_at BEFORE UPDATE ON user_activity FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_channel_category_updated_at ON channel_category;
CREATE TRIGGER trg_channel_category_updated_at BEFORE UPDATE ON channel_category FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_channel_permission_overwrite_updated_at ON channel_permission_overwrite;
CREATE TRIGGER trg_channel_permission_overwrite_updated_at BEFORE UPDATE ON channel_permission_overwrite FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_im_integration_updated_at ON im_integration;
CREATE TRIGGER trg_im_integration_updated_at BEFORE UPDATE ON im_integration FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_message_draft_updated_at ON message_draft;
CREATE TRIGGER trg_message_draft_updated_at BEFORE UPDATE ON message_draft FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_custom_emoji_updated_at ON custom_emoji;
CREATE TRIGGER trg_custom_emoji_updated_at BEFORE UPDATE ON custom_emoji FOR EACH ROW EXECUTE FUNCTION set_updated_at();

DROP TRIGGER IF EXISTS trg_thread_read_state_updated_at ON thread_read_state;
CREATE TRIGGER trg_thread_read_state_updated_at BEFORE UPDATE ON thread_read_state FOR EACH ROW EXECUTE FUNCTION set_updated_at();
