-- ============================================================================
-- Africa Alert — Supabase tenant_id reconciliation script
-- Paste into Supabase SQL Editor, then RUN.
-- Safe to re-run (idempotent).
-- Tenant UUID hard-coded below (matches local system_settings.tenant_id).
-- ============================================================================

DO $script$
DECLARE
  v_tenant_id uuid := '5b39bcb5-506a-456d-b7cb-91730b397cc1';
BEGIN

  -- Sanity check: tenant must exist in the tenants table.
  IF NOT EXISTS (SELECT 1 FROM public.tenants WHERE id = v_tenant_id) THEN
    RAISE EXCEPTION 'Tenant % not found in public.tenants. Insert it first or re-run the registration cycle on the server.', v_tenant_id;
  END IF;

  ---------------------------------------------------------------------------
  -- 1. Backfill null tenant_id on every business table that carries one
  --    (skip 'tenants' itself, plus 'notices' / 'sync_logs' / 'sync_metadata'
  --    / 'sync_config' which don't have a tenant_id column).
  ---------------------------------------------------------------------------
  UPDATE public.admission_enquiries    SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.applicants             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.assignments            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.attendance             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.attendance_new         SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.calendar_events        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.classes                SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.club_announcements     SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.club_attendance        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.club_chats             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.club_memberships       SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.clubs                  SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.complaints             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.course_enrolments      SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.course_grades          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.courses                SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.crossword_clues        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.crossword_games        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.crossword_sessions     SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.departments            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.enrollments            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.events                 SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.exam_answers           SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.exam_attempts          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.exam_groups            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.exam_schedules         SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.expenses               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.fee_groups             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.grades                 SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.hostel_attendance      SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.hostel_fees            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.hostels                SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.item_categories        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.item_issues            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.item_stock             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.items                  SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.leave_requests         SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.leave_types            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.library_books          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.library_fines          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.library_issues         SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.library_reservations   SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.messages               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.messages_new           SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.parent_students        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.payments               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.payroll_runs           SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.payslips               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.phone_call_logs        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.pickup_points          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.postal_dispatch        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.question_banks         SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.room_assignments       SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.room_types             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.rooms                  SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.routes                 SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.salary_grades          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.settings               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.staff_attendance       SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.staff_records          SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.staff_roles            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.stock_transactions     SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.store_locations        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.student_fees           SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.subjects               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.subjects_new           SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.submissions            SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.suppliers              SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.system_settings        SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.transport_allocations  SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.transport_attendance   SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.users                  SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.vacancies              SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.vehicle_routes         SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.vehicles               SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.visitor_logs           SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;
  UPDATE public.audit_logs             SET tenant_id = v_tenant_id WHERE tenant_id IS NULL;

  ---------------------------------------------------------------------------
  -- 2. Enforce NOT NULL now that all rows have a tenant.
  --    Wrapped in dynamic SQL + DO blocks so missing columns don't blow up.
  ---------------------------------------------------------------------------
  PERFORM (
    SELECT string_agg(
      format('ALTER TABLE public.%I ALTER COLUMN tenant_id SET NOT NULL', t.table_name),
      '; '
    )
    FROM information_schema.columns
    WHERE table_schema = 'public'
      AND column_name  = 'tenant_id'
      AND is_nullable  = 'YES'
      AND table_name  <> 'tenants'
  )::text;

  IF (SELECT string_agg(
        format('ALTER TABLE public.%I ALTER COLUMN tenant_id SET NOT NULL', t.table_name), '; ')
      FROM information_schema.columns
      WHERE table_schema='public' AND column_name='tenant_id'
        AND is_nullable='YES' AND table_name <> 'tenants') IS NOT NULL THEN
    EXECUTE (
      SELECT string_agg(
        format('ALTER TABLE public.%I ALTER COLUMN tenant_id SET NOT NULL', t.table_name),
        '; '
      )
      FROM information_schema.columns
      WHERE table_schema = 'public'
        AND column_name  = 'tenant_id'
        AND is_nullable  = 'YES'
        AND table_name  <> 'tenants'
    );
  END IF;

  ---------------------------------------------------------------------------
  -- 3. Indexes on tenant_id (RLS checks every row; you want these).
  ---------------------------------------------------------------------------
  PERFORM (
    SELECT string_agg(
      format('CREATE INDEX IF NOT EXISTS %I ON public.%I (tenant_id)', t.table_name || '_tenant_id_idx', t.table_name),
      '; '
    )
    FROM information_schema.columns
    WHERE table_schema = 'public'
      AND column_name  = 'tenant_id'
      AND table_name  <> 'tenants'
  );

  IF (SELECT string_agg(
        format('CREATE INDEX IF NOT EXISTS %I ON public.%I (tenant_id)', t.table_name || '_tenant_id_idx', t.table_name), '; ')
      FROM information_schema.columns
      WHERE table_schema='public' AND column_name='tenant_id'
        AND table_name <> 'tenants') IS NOT NULL THEN
    EXECUTE (
      SELECT string_agg(
        format('CREATE INDEX IF NOT EXISTS %I ON public.%I (tenant_id)', t.table_name || '_tenant_id_idx', t.table_name),
        '; '
      )
      FROM information_schema.columns
      WHERE table_schema = 'public'
        AND column_name  = 'tenant_id'
        AND table_name  <> 'tenants'
    );
  END IF;

  RAISE NOTICE 'Tenant % reconciled: rows backfilled, NOT NULL enforced, indexes created.', v_tenant_id;
END
$script$;


-- ============================================================================
-- 4. Enable RLS + tenant-isolation policies on every tenant_id-bearing table.
--    service_role key bypasses RLS, so the sync engine still has full access.
--    Run as a separate batch (RLS changes can't be inside the DO block).
-- ============================================================================

DO $rls$
DECLARE
  r record;
BEGIN
  FOR r IN
    SELECT c.table_name
    FROM information_schema.columns c
    WHERE c.table_schema = 'public'
      AND c.column_name  = 'tenant_id'
      AND c.table_name  <> 'tenants'
  LOOP
    EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', r.table_name);

    -- Drop any prior version of our policy to keep this idempotent.
    EXECUTE format('DROP POLICY IF EXISTS tenant_isolation ON public.%I', r.table_name);

    EXECUTE format(
      'CREATE POLICY tenant_isolation ON public.%I
         USING (tenant_id::text = current_setting(''app.current_tenant'', true))
         WITH CHECK (tenant_id::text = current_setting(''app.current_tenant'', true))',
      r.table_name
    );
  END LOOP;
END
$rls$;