-- Students can belong to multiple classes: add StudentClass junction table and remove Student.classId

-- 1. Create junction table
CREATE TABLE "StudentClass" (
  "studentId" TEXT NOT NULL REFERENCES "Student"("id") ON DELETE CASCADE,
  "classId" INTEGER NOT NULL REFERENCES "Class"("id") ON DELETE CASCADE,
  CONSTRAINT "StudentClass_pkey" PRIMARY KEY ("studentId", "classId")
);

CREATE INDEX "StudentClass_classId_idx" ON "StudentClass"("classId");
CREATE INDEX "StudentClass_studentId_idx" ON "StudentClass"("studentId");

-- 2. Backfill from existing Student.classId
INSERT INTO "StudentClass" ("studentId", "classId")
SELECT id, "classId" FROM "Student" WHERE "classId" IS NOT NULL;

-- 3. Drop FK and column on Student
ALTER TABLE "Student" DROP CONSTRAINT IF EXISTS "Student_classId_fkey";
ALTER TABLE "Student" DROP COLUMN IF EXISTS "classId";

-- 4. RLS for StudentClass
ALTER TABLE "StudentClass" ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Admins have full access" ON "StudentClass" FOR ALL USING (
  EXISTS (SELECT 1 FROM "Admin" WHERE id = requesting_user_id())
);

CREATE POLICY "Users can view permitted student-class links" ON "StudentClass" FOR SELECT USING (
  is_admin()
  OR ("studentId" = requesting_user_id() AND requesting_user_role() = 'student')
  OR ("studentId" IN (SELECT id FROM "Student" WHERE "parentId" = requesting_user_id()) AND requesting_user_role() = 'parent')
  OR ("classId" IN (SELECT "classId" FROM "Lesson" WHERE "teacherId" = requesting_user_id()) AND requesting_user_role() = 'teacher')
  OR ("classId" IN (SELECT id FROM "Class" WHERE "supervisorId" = requesting_user_id()) AND requesting_user_role() = 'teacher')
);

CREATE POLICY "Admins can insert student-class" ON "StudentClass" FOR INSERT WITH CHECK (is_admin());
CREATE POLICY "Admins can update student-class" ON "StudentClass" FOR UPDATE USING (is_admin());
CREATE POLICY "Admins can delete student-class" ON "StudentClass" FOR DELETE USING (is_admin());

-- 5. Update auth helper: classes the user can see (student/parent via StudentClass, teacher via Lesson/Class)
CREATE OR REPLACE FUNCTION auth_user_classes() RETURNS SETOF integer LANGUAGE plpgsql SECURITY DEFINER SET search_path = public STABLE AS $$
BEGIN
    RETURN QUERY
    SELECT "classId" FROM "StudentClass" WHERE "studentId" = requesting_user_id() AND requesting_user_role() = 'student'
    UNION
    SELECT "classId" FROM "StudentClass" WHERE "studentId" IN (SELECT id FROM "Student" WHERE "parentId" = requesting_user_id()) AND requesting_user_role() = 'parent'
    UNION
    SELECT "classId" FROM "Lesson" WHERE "teacherId" = requesting_user_id() AND requesting_user_role() = 'teacher'
    UNION
    SELECT id FROM "Class" WHERE "supervisorId" = requesting_user_id() AND requesting_user_role() = 'teacher';
END;
$$;

-- 6. Update auth_user_students: teacher sees students in their classes via StudentClass
CREATE OR REPLACE FUNCTION auth_user_students() RETURNS SETOF text LANGUAGE plpgsql SECURITY DEFINER SET search_path = public STABLE AS $$
BEGIN
    RETURN QUERY
    SELECT id FROM "Student" WHERE id = requesting_user_id() AND requesting_user_role() = 'student'
    UNION
    SELECT id FROM "Student" WHERE "parentId" = requesting_user_id() AND requesting_user_role() = 'parent'
    UNION
    SELECT "studentId" FROM "StudentClass" WHERE "classId" IN (
        SELECT "classId" FROM "Lesson" WHERE "teacherId" = requesting_user_id()
    ) AND requesting_user_role() = 'teacher';
END;
$$;

-- 7. Update auth_user_lessons: student/parent see lessons for any of their classes (via StudentClass)
CREATE OR REPLACE FUNCTION auth_user_lessons() RETURNS SETOF integer LANGUAGE plpgsql SECURITY DEFINER SET search_path = public STABLE AS $$
BEGIN
    RETURN QUERY
    SELECT id FROM "Lesson" WHERE "teacherId" = requesting_user_id() AND requesting_user_role() = 'teacher'
    UNION
    SELECT id FROM "Lesson" WHERE "classId" IN (
        SELECT "classId" FROM "StudentClass" WHERE "studentId" = requesting_user_id() AND requesting_user_role() = 'student'
    )
    UNION
    SELECT id FROM "Lesson" WHERE "classId" IN (
        SELECT "classId" FROM "StudentClass" WHERE "studentId" IN (SELECT id FROM "Student" WHERE "parentId" = requesting_user_id()) AND requesting_user_role() = 'parent'
    );
END;
$$;

-- 8. Update auth_user_subjects
CREATE OR REPLACE FUNCTION auth_user_subjects() RETURNS SETOF integer LANGUAGE plpgsql SECURITY DEFINER SET search_path = public STABLE AS $$
BEGIN
    RETURN QUERY
    SELECT "A" FROM "_SubjectToTeacher" WHERE "B" = requesting_user_id() AND requesting_user_role() = 'teacher'
    UNION
    SELECT "subjectId" FROM "Lesson" WHERE "classId" IN (
        SELECT "classId" FROM "StudentClass" WHERE "studentId" = requesting_user_id() AND requesting_user_role() = 'student'
    )
    UNION
    SELECT "subjectId" FROM "Lesson" WHERE "classId" IN (
        SELECT "classId" FROM "StudentClass" WHERE "studentId" IN (SELECT id FROM "Student" WHERE "parentId" = requesting_user_id()) AND requesting_user_role() = 'parent'
    );
END;
$$;

-- 9. Update auth_user_teachers
CREATE OR REPLACE FUNCTION auth_user_teachers() RETURNS SETOF text LANGUAGE plpgsql SECURITY DEFINER SET search_path = public STABLE AS $$
BEGIN
    RETURN QUERY
    SELECT id FROM "Teacher" WHERE id = requesting_user_id() AND requesting_user_role() = 'teacher'
    UNION
    SELECT "teacherId" FROM "Lesson" WHERE "classId" IN (
        SELECT "classId" FROM "StudentClass" WHERE "studentId" = requesting_user_id() AND requesting_user_role() = 'student'
    )
    UNION
    SELECT "teacherId" FROM "Lesson" WHERE "classId" IN (
        SELECT "classId" FROM "StudentClass" WHERE "studentId" IN (SELECT id FROM "Student" WHERE "parentId" = requesting_user_id()) AND requesting_user_role() = 'parent'
    );
END;
$$;

-- 10. Class policy referenced classId on Student; Student no longer has classId. Policy uses auth_user_classes() which we updated.
-- Event/Announcement policies use auth_user_classes() - no change needed.
