-- For generate_short_uuid
CREATE
OR REPLACE FUNCTION public.generate_short_uuid () RETURNS TEXT AS $$
DECLARE
chars TEXT := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    result
TEXT := '';
    i
INTEGER := 0;
    max_attempts
INTEGER := 10;
    current_attempt
INTEGER := 0;
    is_unique
BOOLEAN := false;
BEGIN
    WHILE
NOT is_unique AND current_attempt < max_attempts LOOP
        result := '';
FOR i IN 1..8 LOOP
            result := result || substr(chars, floor(random() * length(chars) + 1)::integer, 1);
END LOOP;

SELECT COUNT(*) = 0
INTO is_unique
FROM public.users
WHERE suuid = result;

current_attempt
:= current_attempt + 1;
END LOOP;

    IF
NOT is_unique THEN
        RAISE EXCEPTION 'Could not generate unique short UUID after % attempts', max_attempts;
END IF;

RETURN result;
END;
$$
LANGUAGE plpgsql;

CREATE
OR REPLACE FUNCTION public.search_users(search_term TEXT)
RETURNS TABLE (
    uuid UUID,
    suuid TEXT,
    username TEXT,
    indexable BOOLEAN
) AS $$
BEGIN
RETURN QUERY
SELECT u.uuid,
       u.suuid::TEXT,
        -- Simplified CASE logic: show username if SUUID match OR (username match AND indexable) CASE
    WHEN u.suuid = search_term OR u.indexable THEN u.username
    ELSE NULL
    END,
       u.indexable
FROM public.users u
WHERE u.suuid = search_term -- Case 1: SUUID match (always show)
   OR (
    u.indexable = true AND -- Case 2: Username match + indexable
    u.username ILIKE '%' || search_term || '%'
    );
END;
$$
LANGUAGE plpgsql;

-- For is_thread_participant
CREATE
OR REPLACE FUNCTION public.is_thread_participant (thread_uuid UUID) RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (SELECT 1
               FROM public.thread_participants
               WHERE thread_id = thread_uuid
                 AND user_uuid = auth.uid());
END;
$$
LANGUAGE plpgsql SECURITY DEFINER;

-- For get_user_threads
CREATE
OR REPLACE FUNCTION public.get_user_threads (user_id UUID) RETURNS TABLE (
  thread_id UUID,
  participants TEXT[],
  messages JSON[]
) AS $$
BEGIN
    IF
NOT EXISTS (
        SELECT 1
        FROM public.thread_participants
        WHERE user_uuid = user_id
    ) THEN
        -- Return empty result if user has no threads
        RETURN;
END IF;

RETURN QUERY
SELECT mt.id,
       array_agg(DISTINCT u.username),
       COALESCE(array_agg(
                        CASE
                            WHEN m.id IS NOT NULL THEN
                                json_build_object(
                                        'id', m.id,
                                        'content', m.content,
                                        'created_at', m.created_at
                                )
                            ELSE NULL END
                ) FILTER(WHERE m.id IS NOT NULL), ARRAY[] ::JSON[])
FROM public.message_threads mt
         JOIN public.thread_participants tp ON mt.id = tp.thread_id
         JOIN public.users u ON tp.user_uuid = u.uuid
         LEFT JOIN public.messages m ON mt.id = m.thread_id
WHERE mt.id IN (SELECT thread_id
                FROM public.thread_participants
                WHERE user_uuid = user_id)
GROUP BY mt.id;
END;
$$
LANGUAGE plpgsql SECURITY DEFINER;
