-- User Badges Migration for BroadcastBeat
-- Adds earned badges (Contributor, Mentor, Expert, Moderator) based on reputation and activity

-- ============================================================
-- 1. USER BADGES TABLE
-- ============================================================
CREATE TABLE IF NOT EXISTS public.user_badges (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES public.user_profiles(id) ON DELETE CASCADE,
    badge_type TEXT NOT NULL CHECK (badge_type IN ('contributor', 'mentor', 'expert', 'moderator')),
    awarded_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    awarded_reason TEXT
);

CREATE UNIQUE INDEX IF NOT EXISTS idx_user_badges_unique
ON public.user_badges (user_id, badge_type);

CREATE INDEX IF NOT EXISTS idx_user_badges_user_id
ON public.user_badges (user_id);

-- ============================================================
-- 2. FUNCTION: EVALUATE AND AWARD BADGES
-- ============================================================
CREATE OR REPLACE FUNCTION public.evaluate_user_badges(p_user_id UUID)
RETURNS VOID
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
DECLARE
    v_reputation INTEGER;
    v_thread_count INTEGER;
    v_reply_count INTEGER;
    v_upvotes_received INTEGER;
    v_is_moderator BOOLEAN := false;
BEGIN
    -- Get reputation
    SELECT COALESCE(reputation, 0) INTO v_reputation
    FROM public.user_profiles WHERE id = p_user_id;

    -- Get thread count
    SELECT COUNT(*) INTO v_thread_count
    FROM public.forum_threads WHERE author_id = p_user_id;

    -- Get reply count
    SELECT COUNT(*) INTO v_reply_count
    FROM public.forum_replies WHERE author_id = p_user_id;

    -- Get total upvotes received
    SELECT COALESCE(SUM(upvotes), 0) INTO v_upvotes_received
    FROM (
        SELECT upvotes FROM public.forum_threads WHERE author_id = p_user_id
        UNION ALL
        SELECT upvotes FROM public.forum_replies WHERE author_id = p_user_id
    ) AS all_posts;

    -- Check moderator role (if user_roles table exists)
    IF EXISTS (
        SELECT 1 FROM information_schema.tables
        WHERE table_schema = 'public' AND table_name = 'user_roles'
    ) THEN
        SELECT EXISTS(
            SELECT 1 FROM public.user_roles
            WHERE user_id = p_user_id AND role IN ('moderator', 'admin')
        ) INTO v_is_moderator;
    END IF;

    -- Award CONTRIBUTOR badge: reputation >= 100 OR (threads >= 5 AND replies >= 10)
    IF v_reputation >= 100 OR (v_thread_count >= 5 AND v_reply_count >= 10) THEN
        INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
        VALUES (p_user_id, 'contributor', 'Reached 100 reputation or posted 5+ threads and 10+ replies')
        ON CONFLICT (user_id, badge_type) DO NOTHING;
    END IF;

    -- Award MENTOR badge: reputation >= 300 OR upvotes_received >= 50
    IF v_reputation >= 300 OR v_upvotes_received >= 50 THEN
        INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
        VALUES (p_user_id, 'mentor', 'Reached 300 reputation or received 50+ upvotes')
        ON CONFLICT (user_id, badge_type) DO NOTHING;
    END IF;

    -- Award EXPERT badge: reputation >= 1000 OR (upvotes_received >= 200 AND thread_count >= 20)
    IF v_reputation >= 1000 OR (v_upvotes_received >= 200 AND v_thread_count >= 20) THEN
        INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
        VALUES (p_user_id, 'expert', 'Reached 1000 reputation or received 200+ upvotes with 20+ threads')
        ON CONFLICT (user_id, badge_type) DO NOTHING;
    END IF;

    -- Award MODERATOR badge: has moderator/admin role
    IF v_is_moderator THEN
        INSERT INTO public.user_badges (user_id, badge_type, awarded_reason)
        VALUES (p_user_id, 'moderator', 'Assigned moderator or admin role')
        ON CONFLICT (user_id, badge_type) DO NOTHING;
    END IF;
END;
$$;

-- ============================================================
-- 3. TRIGGER FUNCTION: AUTO-EVALUATE BADGES ON REPUTATION CHANGE
-- ============================================================
CREATE OR REPLACE FUNCTION public.trigger_evaluate_badges()
RETURNS TRIGGER
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
    PERFORM public.evaluate_user_badges(NEW.id);
    RETURN NEW;
END;
$$;

-- ============================================================
-- 4. ENABLE RLS
-- ============================================================
ALTER TABLE public.user_badges ENABLE ROW LEVEL SECURITY;

-- ============================================================
-- 5. RLS POLICIES
-- ============================================================
DROP POLICY IF EXISTS "public_read_user_badges" ON public.user_badges;
CREATE POLICY "public_read_user_badges"
ON public.user_badges FOR SELECT TO public USING (true);

DROP POLICY IF EXISTS "service_role_manage_user_badges" ON public.user_badges;
CREATE POLICY "service_role_manage_user_badges"
ON public.user_badges FOR ALL TO service_role USING (true) WITH CHECK (true);

-- ============================================================
-- 6. TRIGGER: EVALUATE BADGES WHEN REPUTATION CHANGES
-- ============================================================
DROP TRIGGER IF EXISTS on_reputation_change_evaluate_badges ON public.user_profiles;
CREATE TRIGGER on_reputation_change_evaluate_badges
AFTER UPDATE OF reputation ON public.user_profiles
FOR EACH ROW
WHEN (OLD.reputation IS DISTINCT FROM NEW.reputation)
EXECUTE FUNCTION public.trigger_evaluate_badges();

-- ============================================================
-- 7. BACKFILL BADGES FOR EXISTING USERS
-- ============================================================
DO $$
DECLARE
    v_user_id UUID;
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.tables
        WHERE table_schema = 'public' AND table_name = 'user_profiles'
    ) THEN
        FOR v_user_id IN SELECT id FROM public.user_profiles LOOP
            PERFORM public.evaluate_user_badges(v_user_id);
        END LOOP;
        RAISE NOTICE 'Badge backfill completed for all existing users.';
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'Badge backfill failed: %', SQLERRM;
END $$;
