-- 011: Announcement Channel — articles, comments, reactions, follows, cross-posts
--
-- New tables:
--   article, article_comment, article_reaction,
--   channel_follow, article_cross_post

-- ============================================================
-- 1. Articles
-- ============================================================

-- models/channels/articles.rs  →  article
CREATE TABLE IF NOT EXISTS article (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    author_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    title TEXT NOT NULL,
    slug TEXT NOT NULL,
    summary TEXT NULL,
    body TEXT NOT NULL,
    cover_image_url TEXT NULL,
    status TEXT NOT NULL,
    visibility TEXT NOT NULL,
    tags TEXT[] NOT NULL,
    published_at TIMESTAMPTZ NULL,
    published_by UUID NULL REFERENCES "user"(id) ON DELETE SET NULL,
    scheduled_at TIMESTAMPTZ NULL,
    unpublished_at TIMESTAMPTZ NULL,
    views_count BIGINT NOT NULL DEFAULT 0,
    comments_count BIGINT NOT NULL DEFAULT 0,
    reactions_count BIGINT NOT NULL DEFAULT 0,
    cross_posted BOOLEAN NOT NULL DEFAULT FALSE,
    cross_posted_from UUID NULL REFERENCES article(id) ON DELETE SET NULL,
    metadata JSONB NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    deleted_at TIMESTAMPTZ NULL,
    CONSTRAINT uq_article_channel_slug UNIQUE (channel_id, slug)
);
CREATE INDEX IF NOT EXISTS idx_article_channel_id ON article (channel_id);
CREATE INDEX IF NOT EXISTS idx_article_author_id ON article (author_id);
CREATE INDEX IF NOT EXISTS idx_article_status ON article (status);
CREATE INDEX IF NOT EXISTS idx_article_published_at ON article (published_at DESC) WHERE published_at IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_article_cross_posted_from ON article (cross_posted_from) WHERE cross_posted_from IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_article_deleted ON article (deleted_at) WHERE deleted_at IS NOT NULL;

-- ============================================================
-- 2. Article Comments
-- ============================================================

-- models/channels/article_comments.rs  →  article_comment
CREATE TABLE IF NOT EXISTS article_comment (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    article_id UUID NOT NULL REFERENCES article(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    author_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    parent_comment_id UUID NULL REFERENCES article_comment(id) ON DELETE CASCADE,
    body TEXT NOT NULL,
    edited_at TIMESTAMPTZ NULL,
    deleted_at TIMESTAMPTZ NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_article_comment_article_id ON article_comment (article_id);
CREATE INDEX IF NOT EXISTS idx_article_comment_author_id ON article_comment (author_id);
CREATE INDEX IF NOT EXISTS idx_article_comment_parent ON article_comment (parent_comment_id) WHERE parent_comment_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_article_comment_deleted ON article_comment (deleted_at) WHERE deleted_at IS NOT NULL;

-- ============================================================
-- 3. Article Reactions
-- ============================================================

-- models/channels/article_reactions.rs  →  article_reaction
CREATE TABLE IF NOT EXISTS article_reaction (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    article_id UUID NOT NULL REFERENCES article(id) ON DELETE CASCADE,
    channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    content TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_article_reaction UNIQUE (article_id, user_id, content)
);
CREATE INDEX IF NOT EXISTS idx_article_reaction_article_id ON article_reaction (article_id);
CREATE INDEX IF NOT EXISTS idx_article_reaction_user_id ON article_reaction (user_id);

-- ============================================================
-- 4. Channel Follows
-- ============================================================

-- models/channels/channel_follows.rs  →  channel_follow
CREATE TABLE IF NOT EXISTS channel_follow (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    source_channel_id UUID NOT NULL REFERENCES channel(id) ON DELETE CASCADE,
    target_workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE,
    target_channel_id UUID NULL REFERENCES channel(id) ON DELETE SET NULL,
    webhook_url TEXT NULL,
    webhook_secret_ciphertext TEXT NULL,
    enabled BOOLEAN NOT NULL,
    followed_by UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE,
    unfollowed_at TIMESTAMPTZ NULL,
    last_delivery_at TIMESTAMPTZ NULL,
    last_delivery_status TEXT NULL,
    created_at TIMESTAMPTZ NOT NULL,
    updated_at TIMESTAMPTZ NOT NULL,
    CONSTRAINT uq_channel_follow_source_target UNIQUE (source_channel_id, target_workspace_id, target_channel_id)
);
CREATE INDEX IF NOT EXISTS idx_channel_follow_source ON channel_follow (source_channel_id);
CREATE INDEX IF NOT EXISTS idx_channel_follow_target_ws ON channel_follow (target_workspace_id);
CREATE INDEX IF NOT EXISTS idx_channel_follow_target_channel ON channel_follow (target_channel_id) WHERE target_channel_id IS NOT NULL;

-- ============================================================
-- 5. Article Cross-Posts
-- ============================================================

-- models/channels/article_cross_posts.rs  →  article_cross_post
CREATE TABLE IF NOT EXISTS article_cross_post (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    article_id UUID NOT NULL REFERENCES article(id) ON DELETE CASCADE,
    follow_id UUID NOT NULL REFERENCES channel_follow(id) ON DELETE CASCADE,
    target_workspace_id UUID NOT NULL REFERENCES workspace(id) ON DELETE CASCADE,
    target_channel_id UUID NULL REFERENCES channel(id) ON DELETE SET NULL,
    status TEXT NOT NULL,
    attempts INTEGER NOT NULL DEFAULT 0,
    last_error TEXT NULL,
    sent_at TIMESTAMPTZ NULL,
    delivered_at TIMESTAMPTZ NULL,
    failed_at TIMESTAMPTZ NULL,
    created_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_article_cross_post_article_id ON article_cross_post (article_id);
CREATE INDEX IF NOT EXISTS idx_article_cross_post_follow_id ON article_cross_post (follow_id);
CREATE INDEX IF NOT EXISTS idx_article_cross_post_status ON article_cross_post (status);
CREATE INDEX IF NOT EXISTS idx_article_cross_post_target_ws ON article_cross_post (target_workspace_id);

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

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

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

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