-- =============================================================================
-- Supabase RPC: match_courses
-- Hybrid Recommender Engine — Vector Similarity Search
-- Searches course_chunks embeddings, JOINs to parent courses table.
-- Supports SBERT, E5, and DistilBERT models via model_type parameter.
-- =============================================================================

-- Drop existing function variants (for idempotent re-runs)
DROP FUNCTION IF EXISTS match_courses(vector, float, int, int, text);
DROP FUNCTION IF EXISTS match_courses(vector, float8, int4, int4, text);

CREATE OR REPLACE FUNCTION match_courses(
    query_embedding vector,
    match_threshold float DEFAULT 0.3,
    match_count int DEFAULT 5,
    child_age_months int DEFAULT 48,
    model_type text DEFAULT 'sbert'
)
RETURNS TABLE (
    course_id uuid,
    course_title text,
    course_description text,
    chunk_id uuid,
    chunk_title text,
    chunk_content text,
    similarity float
)
LANGUAGE plpgsql
AS $$
BEGIN
    IF model_type = 'e5' THEN
        RETURN QUERY
        SELECT
            c.id AS course_id,
            c.title AS course_title,
            c.description AS course_description,
            cc.id AS chunk_id,
            cc.chunk_title,
            cc.chunk_content,
            (1 - (cc.embedding_e5 <=> query_embedding))::float AS similarity
        FROM course_chunks cc
        JOIN courses c ON cc.course_id = c.id
        WHERE
            c.age_min <= child_age_months
            AND c.age_max >= child_age_months
            AND cc.embedding_e5 IS NOT NULL
            AND (1 - (cc.embedding_e5 <=> query_embedding)) > match_threshold
        ORDER BY cc.embedding_e5 <=> query_embedding ASC
        LIMIT match_count;

    ELSIF model_type = 'distilbert' THEN
        RETURN QUERY
        SELECT
            c.id AS course_id,
            c.title AS course_title,
            c.description AS course_description,
            cc.id AS chunk_id,
            cc.chunk_title,
            cc.chunk_content,
            (1 - (cc.embedding_distilbert <=> query_embedding))::float AS similarity
        FROM course_chunks cc
        JOIN courses c ON cc.course_id = c.id
        WHERE
            c.age_min <= child_age_months
            AND c.age_max >= child_age_months
            AND cc.embedding_distilbert IS NOT NULL
            AND (1 - (cc.embedding_distilbert <=> query_embedding)) > match_threshold
        ORDER BY cc.embedding_distilbert <=> query_embedding ASC
        LIMIT match_count;

    ELSE
        -- Default: SBERT
        RETURN QUERY
        SELECT
            c.id AS course_id,
            c.title AS course_title,
            c.description AS course_description,
            cc.id AS chunk_id,
            cc.chunk_title,
            cc.chunk_content,
            (1 - (cc.embedding_sbert <=> query_embedding))::float AS similarity
        FROM course_chunks cc
        JOIN courses c ON cc.course_id = c.id
        WHERE
            c.age_min <= child_age_months
            AND c.age_max >= child_age_months
            AND cc.embedding_sbert IS NOT NULL
            AND (1 - (cc.embedding_sbert <=> query_embedding)) > match_threshold
        ORDER BY cc.embedding_sbert <=> query_embedding ASC
        LIMIT match_count;
    END IF;
END;
$$;
