-- 000011_tagging_system.up.sql
-- Complete tagging system for hashtags and mentions

-- Hashtags master table
CREATE TABLE IF NOT EXISTS hashtags (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name TEXT NOT NULL, -- lowercase, without #
    display_name TEXT NOT NULL, -- original casing
    use_count INTEGER NOT NULL DEFAULT 0,
    trending_score FLOAT NOT NULL DEFAULT 0,
    is_trending BOOLEAN NOT NULL DEFAULT FALSE,
    is_featured BOOLEAN NOT NULL DEFAULT FALSE,
    category TEXT, -- optional category grouping
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(name)
);

-- Post-to-hashtag junction table
CREATE TABLE IF NOT EXISTS post_hashtags (
    post_id UUID NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
    hashtag_id UUID NOT NULL REFERENCES hashtags(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    PRIMARY KEY (post_id, hashtag_id)
);

-- User-to-hashtag follows (users can follow hashtags)
CREATE TABLE IF NOT EXISTS hashtag_follows (
    user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
    hashtag_id UUID NOT NULL REFERENCES hashtags(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    PRIMARY KEY (user_id, hashtag_id)
);

-- Post mentions (tracks @mentions in posts)
CREATE TABLE IF NOT EXISTS post_mentions (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    post_id UUID NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
    mentioned_user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(post_id, mentioned_user_id)
);

-- Trending hashtags snapshot (for discover page)
CREATE TABLE IF NOT EXISTS trending_hashtags (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    hashtag_id UUID NOT NULL REFERENCES hashtags(id) ON DELETE CASCADE,
    rank INTEGER NOT NULL,
    calculated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    period TEXT NOT NULL DEFAULT 'daily', -- 'hourly', 'daily', 'weekly'
    post_count_in_period INTEGER NOT NULL DEFAULT 0,
    UNIQUE(hashtag_id, period)
);

-- Suggested users for discover page
CREATE TABLE IF NOT EXISTS suggested_users (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    user_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
    reason TEXT NOT NULL, -- 'popular', 'category', 'similar', 'new_creator'
    category TEXT,
    score FLOAT NOT NULL DEFAULT 0,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(user_id, reason)
);

-- Indexes for performance
CREATE INDEX IF NOT EXISTS idx_hashtags_name ON hashtags(name);
CREATE INDEX IF NOT EXISTS idx_hashtags_trending ON hashtags(is_trending, trending_score DESC);
CREATE INDEX IF NOT EXISTS idx_hashtags_use_count ON hashtags(use_count DESC);
CREATE INDEX IF NOT EXISTS idx_post_hashtags_hashtag ON post_hashtags(hashtag_id);
CREATE INDEX IF NOT EXISTS idx_post_mentions_user ON post_mentions(mentioned_user_id);
CREATE INDEX IF NOT EXISTS idx_trending_hashtags_rank ON trending_hashtags(period, rank);
CREATE INDEX IF NOT EXISTS idx_suggested_users_active ON suggested_users(is_active, score DESC);

-- Function to update hashtag use count
CREATE OR REPLACE FUNCTION update_hashtag_count()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        UPDATE hashtags SET use_count = use_count + 1, updated_at = NOW() WHERE id = NEW.hashtag_id;
    ELSIF TG_OP = 'DELETE' THEN
        UPDATE hashtags SET use_count = GREATEST(0, use_count - 1), updated_at = NOW() WHERE id = OLD.hashtag_id;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS hashtag_count_trigger ON post_hashtags;
CREATE TRIGGER hashtag_count_trigger
    AFTER INSERT OR DELETE ON post_hashtags
    FOR EACH ROW
    EXECUTE FUNCTION update_hashtag_count();

-- Function to calculate trending score (decay-based)
CREATE OR REPLACE FUNCTION calculate_trending_scores()
RETURNS void AS $$
DECLARE
    decay_factor FLOAT := 0.95;
    hours_window INTEGER := 24;
BEGIN
    -- Calculate trending score based on recent usage with time decay
    UPDATE hashtags h
    SET 
        trending_score = COALESCE((
            SELECT SUM(POWER(decay_factor, EXTRACT(EPOCH FROM (NOW() - ph.created_at)) / 3600))
            FROM post_hashtags ph
            WHERE ph.hashtag_id = h.id
            AND ph.created_at > NOW() - INTERVAL '24 hours'
        ), 0),
        is_trending = (
            SELECT COUNT(*) >= 5
            FROM post_hashtags ph
            WHERE ph.hashtag_id = h.id
            AND ph.created_at > NOW() - INTERVAL '24 hours'
        ),
        updated_at = NOW();
    
    -- Update trending_hashtags table
    DELETE FROM trending_hashtags WHERE period = 'daily';
    INSERT INTO trending_hashtags (hashtag_id, rank, period, post_count_in_period)
    SELECT 
        h.id,
        ROW_NUMBER() OVER (ORDER BY h.trending_score DESC),
        'daily',
        (SELECT COUNT(*) FROM post_hashtags ph WHERE ph.hashtag_id = h.id AND ph.created_at > NOW() - INTERVAL '24 hours')
    FROM hashtags h
    WHERE h.trending_score > 0
    ORDER BY h.trending_score DESC
    LIMIT 50;
END;
$$ LANGUAGE plpgsql;
