-- ============================================================
-- Kreş SaaS — Schema İzolasyonundan tenantId Column Yaklaşımına Geçiş
-- Bu dosyayı Supabase SQL Editor'dan çalıştırın.
-- İdempotent: birden fazla kez çalıştırılabilir.
-- ============================================================

-- ============================================================
-- 1. ENUM TİPLER
-- ============================================================

DO $$ BEGIN
  CREATE TYPE "Plan" AS ENUM ('TRIAL', 'STARTER', 'GROWTH', 'ENTERPRISE');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "SubscriptionStatus" AS ENUM ('TRIAL', 'ACTIVE', 'SUSPENDED', 'CANCELLED');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "Role" AS ENUM ('ADMIN', 'TEACHER', 'PARENT');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "Gender" AS ENUM ('MALE', 'FEMALE');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "AttendanceStatus" AS ENUM ('PRESENT', 'ABSENT', 'LATE', 'EXCUSED');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "DailyLogType" AS ENUM ('MEAL', 'SLEEP', 'MEDICINE', 'NOTE', 'OBSERVATION');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "InvoiceStatus" AS ENUM ('PENDING', 'PAID', 'OVERDUE', 'CANCELLED');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "PaymentStatus" AS ENUM ('PENDING', 'SUCCESS', 'FAILED', 'REFUNDED');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- ============================================================
-- 1b. SIFIR VERİTABANI (Supabase yeni proje): platform tabloları yoksa oluştur
-- Hata "relation public.tenants does not exist" → bu blok çözüm sağlar.
-- Zaten 01_public_schema.sql çalıştırdıysan bu blok atlanır (tablo vardır).
-- ============================================================

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = 'public' AND table_name = 'tenants'
  ) THEN
    CREATE TABLE public.tenants (
      id         TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
      name       TEXT        NOT NULL,
      slug       TEXT        NOT NULL UNIQUE,
      email      TEXT        NOT NULL UNIQUE,
      phone      TEXT,
      city       TEXT,
      address    TEXT,
      logo_url   TEXT,
      plan       TEXT        NOT NULL DEFAULT 'TRIAL',
      is_active  BOOLEAN     NOT NULL DEFAULT true,
      created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
      updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
    );
    CREATE INDEX IF NOT EXISTS tenants_slug_idx ON public.tenants (slug);
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = 'public' AND table_name = 'subscriptions'
  ) THEN
    CREATE TABLE public.subscriptions (
      id           TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
      tenant_id    TEXT        NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
      plan         TEXT        NOT NULL DEFAULT 'TRIAL',
      status       TEXT        NOT NULL DEFAULT 'TRIAL',
      max_students INT         NOT NULL DEFAULT 50,
      max_branches INT         NOT NULL DEFAULT 1,
      starts_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
      ends_at      TIMESTAMPTZ,
      created_at   TIMESTAMPTZ NOT NULL DEFAULT now()
    );
    CREATE INDEX IF NOT EXISTS subscriptions_tenant_id_idx ON public.subscriptions (tenant_id);
  END IF;
END $$;

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = 'public' AND table_name = 'super_admins'
  ) AND NOT EXISTS (
    SELECT 1 FROM information_schema.tables
    WHERE table_schema = 'public' AND table_name = 'platform_admins'
  ) THEN
    CREATE TABLE public.super_admins (
      id            TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
      email         TEXT        NOT NULL UNIQUE,
      password_hash TEXT        NOT NULL,
      full_name     TEXT        NOT NULL,
      is_active     BOOLEAN     NOT NULL DEFAULT true,
      last_login_at TIMESTAMPTZ,
      created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
    );
  END IF;
END $$;

-- ============================================================
-- 2. TENANTS TABLOSU — schema_name KALDIRMA + plan ENUM'A ÇEVİRME
-- ============================================================

-- plan kolonunu ENUM tipine çevir
DO $$ BEGIN
  ALTER TABLE public.tenants
    ALTER COLUMN plan TYPE "Plan" USING plan::"Plan";
EXCEPTION WHEN others THEN NULL;
END $$;

-- schema_name kolonunu kaldır (artık gerekli değil)
ALTER TABLE public.tenants DROP COLUMN IF EXISTS schema_name;

-- ============================================================
-- 3. SUBSCRIPTIONS TABLOSU — ENUM'A ÇEVİRME
-- ============================================================

DO $$ BEGIN
  ALTER TABLE public.subscriptions
    ALTER COLUMN plan TYPE "Plan" USING plan::"Plan",
    ALTER COLUMN status TYPE "SubscriptionStatus" USING status::"SubscriptionStatus";
EXCEPTION WHEN others THEN NULL;
END $$;

-- ============================================================
-- 4. SUPER_ADMINS → PLATFORM_ADMINS YENİDEN ADLANDIRMA
-- ============================================================

DO $$ BEGIN
  ALTER TABLE public.super_admins RENAME TO platform_admins;
EXCEPTION WHEN undefined_table THEN NULL;
          WHEN duplicate_table THEN NULL;
END $$;

-- ============================================================
-- 4b. EKSİK tenant_id KOLONU (42703 önlemi)
-- Tablo daha önce oluştuysa (Supabase profile users, Prisma db push vb.)
-- CREATE TABLE IF NOT EXISTS atlanır; index tenant_id arar → hata.
-- ============================================================

DO $$
BEGIN
  IF to_regclass('public.subscriptions') IS NOT NULL THEN
    ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.users') IS NOT NULL THEN
    ALTER TABLE public.users ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.branches') IS NOT NULL THEN
    ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.classrooms') IS NOT NULL THEN
    ALTER TABLE public.classrooms ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.students') IS NOT NULL THEN
    ALTER TABLE public.students ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.attendance') IS NOT NULL THEN
    ALTER TABLE public.attendance ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.daily_logs') IS NOT NULL THEN
    ALTER TABLE public.daily_logs ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.messages') IS NOT NULL THEN
    ALTER TABLE public.messages ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.invoices') IS NOT NULL THEN
    ALTER TABLE public.invoices ADD COLUMN IF NOT EXISTS tenant_id TEXT REFERENCES public.tenants(id) ON DELETE CASCADE;
  END IF;
  IF to_regclass('public.audit_logs') IS NOT NULL THEN
    ALTER TABLE public.audit_logs ADD COLUMN IF NOT EXISTS tenant_id TEXT;
  END IF;
END $$;

-- ============================================================
-- 5. USERS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.users (
  id            TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id     TEXT        NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  email         TEXT        NOT NULL,
  password_hash TEXT        NOT NULL,
  role          "Role"      NOT NULL DEFAULT 'ADMIN',
  full_name     TEXT        NOT NULL,
  phone         TEXT,
  photo_url     TEXT,
  is_active     BOOLEAN     NOT NULL DEFAULT true,
  last_login_at TIMESTAMPTZ,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now(),

  UNIQUE(tenant_id, email)
);

CREATE INDEX IF NOT EXISTS users_tenant_id_idx ON public.users (tenant_id);
CREATE INDEX IF NOT EXISTS users_tenant_id_role_idx ON public.users (tenant_id, role);

-- ============================================================
-- 6. BRANCHES TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.branches (
  id         TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id  TEXT        NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  name       TEXT        NOT NULL,
  address    TEXT,
  phone      TEXT,
  is_active  BOOLEAN     NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS branches_tenant_id_idx ON public.branches (tenant_id);

-- ============================================================
-- 7. CLASSROOMS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.classrooms (
  id         TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id  TEXT        NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  branch_id  TEXT        NOT NULL REFERENCES public.branches(id) ON DELETE CASCADE,
  name       TEXT        NOT NULL,
  capacity   INT         NOT NULL DEFAULT 20,
  age_group  TEXT,
  is_active  BOOLEAN     NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS classrooms_tenant_id_idx ON public.classrooms (tenant_id);
CREATE INDEX IF NOT EXISTS classrooms_tenant_branch_idx ON public.classrooms (tenant_id, branch_id);

-- ============================================================
-- 8. STUDENTS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.students (
  id            TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id     TEXT        NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  classroom_id  TEXT        REFERENCES public.classrooms(id) ON DELETE SET NULL,
  first_name    TEXT        NOT NULL,
  last_name     TEXT        NOT NULL,
  birth_date    DATE,
  gender        "Gender",
  photo_url     TEXT,
  blood_type    TEXT,
  allergies     TEXT,
  medical_notes TEXT,
  is_active     BOOLEAN     NOT NULL DEFAULT true,
  enrolled_at   DATE        NOT NULL DEFAULT CURRENT_DATE,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS students_tenant_id_idx ON public.students (tenant_id);
CREATE INDEX IF NOT EXISTS students_tenant_classroom_idx ON public.students (tenant_id, classroom_id);

-- ============================================================
-- 9. PARENTS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.parents (
  id            TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  user_id       TEXT        NOT NULL UNIQUE REFERENCES public.users(id) ON DELETE CASCADE,
  relation_type TEXT        NOT NULL DEFAULT 'PARENT',
  occupation    TEXT,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- ============================================================
-- 10. STUDENT_PARENTS (BAĞLANTI) TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.student_parents (
  student_id TEXT    NOT NULL REFERENCES public.students(id) ON DELETE CASCADE,
  parent_id  TEXT    NOT NULL REFERENCES public.parents(id) ON DELETE CASCADE,
  is_primary BOOLEAN NOT NULL DEFAULT false,
  can_pickup BOOLEAN NOT NULL DEFAULT true,

  PRIMARY KEY (student_id, parent_id)
);

-- ============================================================
-- 11. ATTENDANCE TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.attendance (
  id           TEXT               PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id    TEXT               NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  student_id   TEXT               NOT NULL REFERENCES public.students(id) ON DELETE CASCADE,
  date         DATE               NOT NULL,
  status       "AttendanceStatus" NOT NULL DEFAULT 'PRESENT',
  arrival_at   TIME,
  departure_at TIME,
  note         TEXT,
  recorded_by  TEXT,
  created_at   TIMESTAMPTZ        NOT NULL DEFAULT now(),

  UNIQUE(tenant_id, student_id, date)
);

CREATE INDEX IF NOT EXISTS attendance_tenant_date_idx ON public.attendance (tenant_id, date);

-- ============================================================
-- 12. DAILY_LOGS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.daily_logs (
  id          TEXT           PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id   TEXT           NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  student_id  TEXT           NOT NULL REFERENCES public.students(id) ON DELETE CASCADE,
  log_date    DATE           NOT NULL DEFAULT CURRENT_DATE,
  log_type    "DailyLogType" NOT NULL,
  data        JSONB          NOT NULL DEFAULT '{}',
  recorded_by TEXT,
  created_at  TIMESTAMPTZ    NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS daily_logs_tenant_student_date_idx ON public.daily_logs (tenant_id, student_id, log_date);

-- ============================================================
-- 13. MESSAGES TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.messages (
  id           TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id    TEXT        NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  from_user_id TEXT        NOT NULL,
  to_user_id   TEXT        NOT NULL,
  body         TEXT        NOT NULL,
  is_read      BOOLEAN     NOT NULL DEFAULT false,
  read_at      TIMESTAMPTZ,
  sent_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS messages_tenant_to_read_idx ON public.messages (tenant_id, to_user_id, is_read);

-- ============================================================
-- 14. INVOICES TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.invoices (
  id           TEXT            PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id    TEXT            NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
  student_id   TEXT            NOT NULL REFERENCES public.students(id) ON DELETE CASCADE,
  title        TEXT            NOT NULL,
  amount       NUMERIC(10, 2) NOT NULL,
  tax_amount   NUMERIC(10, 2) NOT NULL DEFAULT 0,
  total_amount NUMERIC(10, 2) NOT NULL,
  due_date     DATE            NOT NULL,
  status       "InvoiceStatus" NOT NULL DEFAULT 'PENDING',
  paid_at      TIMESTAMPTZ,
  notes        TEXT,
  created_at   TIMESTAMPTZ     NOT NULL DEFAULT now(),
  updated_at   TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS invoices_tenant_student_idx ON public.invoices (tenant_id, student_id);
CREATE INDEX IF NOT EXISTS invoices_tenant_status_idx ON public.invoices (tenant_id, status);
CREATE INDEX IF NOT EXISTS invoices_tenant_due_date_idx ON public.invoices (tenant_id, due_date);

-- ============================================================
-- 15. PAYMENTS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.payments (
  id           TEXT            PRIMARY KEY DEFAULT gen_random_uuid()::text,
  invoice_id   TEXT            NOT NULL REFERENCES public.invoices(id) ON DELETE CASCADE,
  amount       NUMERIC(10, 2) NOT NULL,
  provider     TEXT            NOT NULL DEFAULT 'iyzico',
  provider_ref TEXT,
  status       "PaymentStatus" NOT NULL DEFAULT 'PENDING',
  paid_at      TIMESTAMPTZ,
  metadata     JSONB,
  created_at   TIMESTAMPTZ     NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS payments_invoice_id_idx ON public.payments (invoice_id);

-- ============================================================
-- 16. AUDIT_LOGS TABLOSU
-- ============================================================

CREATE TABLE IF NOT EXISTS public.audit_logs (
  id         TEXT        PRIMARY KEY DEFAULT gen_random_uuid()::text,
  tenant_id  TEXT,
  user_id    TEXT,
  action     TEXT        NOT NULL,
  entity     TEXT        NOT NULL,
  entity_id  TEXT,
  old_data   JSONB,
  new_data   JSONB,
  ip_address TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS audit_logs_tenant_entity_idx ON public.audit_logs (tenant_id, entity);
CREATE INDEX IF NOT EXISTS audit_logs_created_at_idx ON public.audit_logs (created_at);

-- ============================================================
-- 17. updated_at TRIGGER'LARI
-- ============================================================

CREATE OR REPLACE FUNCTION public.set_updated_at()
RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$;

DROP TRIGGER IF EXISTS tenants_updated_at ON public.tenants;
CREATE TRIGGER tenants_updated_at
  BEFORE UPDATE ON public.tenants
  FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

DROP TRIGGER IF EXISTS users_updated_at ON public.users;
CREATE TRIGGER users_updated_at
  BEFORE UPDATE ON public.users
  FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

DROP TRIGGER IF EXISTS students_updated_at ON public.students;
CREATE TRIGGER students_updated_at
  BEFORE UPDATE ON public.students
  FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

DROP TRIGGER IF EXISTS invoices_updated_at ON public.invoices;
CREATE TRIGGER invoices_updated_at
  BEFORE UPDATE ON public.invoices
  FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();

-- ============================================================
-- 18. ESKİ YAPIYI TEMİZLE
-- ============================================================

-- create_tenant_schema fonksiyonunu kaldır
DROP FUNCTION IF EXISTS public.create_tenant_schema(TEXT);

-- ============================================================
-- 19. VERİ MİGRASYONU (Mevcut tenant şemalarından)
-- Eğer mevcut tenant şemalarında veri varsa, aşağıdaki bloğu
-- çalıştırarak verileri public şemaya taşıyabilirsiniz.
-- Her tenant için tenant_id eklenerek INSERT yapılır.
-- ============================================================

DO $$
DECLARE
  t RECORD;
  schema_exists BOOLEAN;
BEGIN
  FOR t IN SELECT id, slug FROM public.tenants LOOP
    -- Tenant şema adını oluştur
    DECLARE
      s_name TEXT := 'tenant_' || REPLACE(t.slug, '-', '_');
    BEGIN
      SELECT EXISTS(
        SELECT 1 FROM information_schema.schemata WHERE schema_name = s_name
      ) INTO schema_exists;

      IF NOT schema_exists THEN
        CONTINUE;
      END IF;

      -- Users
      EXECUTE format('
        INSERT INTO public.users (id, tenant_id, email, password_hash, role, full_name, phone, photo_url, is_active, last_login_at, created_at, updated_at)
        SELECT id, %L, email, password_hash, role::"Role", full_name, phone, avatar_url, is_active, last_login_at, created_at, updated_at
        FROM %I.users
        ON CONFLICT (tenant_id, email) DO NOTHING
      ', t.id, s_name);

      -- Branches
      EXECUTE format('
        INSERT INTO public.branches (id, tenant_id, name, address, phone, is_active, created_at)
        SELECT id, %L, name, address, phone, is_active, created_at
        FROM %I.branches
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Classrooms
      EXECUTE format('
        INSERT INTO public.classrooms (id, tenant_id, branch_id, name, capacity, age_group, is_active, created_at)
        SELECT id, %L, branch_id, name, capacity, age_group, is_active, created_at
        FROM %I.classrooms
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Students
      EXECUTE format('
        INSERT INTO public.students (id, tenant_id, classroom_id, first_name, last_name, birth_date, gender, photo_url, blood_type, allergies, medical_notes, is_active, enrolled_at, created_at, updated_at)
        SELECT id, %L, classroom_id, first_name, last_name, birth_date,
               CASE WHEN gender IS NOT NULL AND gender IN (''MALE'', ''FEMALE'') THEN gender::"Gender" ELSE NULL END,
               photo_url, blood_type, allergies, medical_notes, is_active, enrollment_date, created_at, updated_at
        FROM %I.students
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Attendance
      EXECUTE format('
        INSERT INTO public.attendance (id, tenant_id, student_id, date, status, arrival_at, departure_at, note, recorded_by, created_at)
        SELECT id, %L, student_id, date,
               CASE WHEN status IN (''PRESENT'', ''ABSENT'', ''LATE'', ''EXCUSED'') THEN status::"AttendanceStatus" ELSE ''PRESENT''::"AttendanceStatus" END,
               check_in_at::time, check_out_at::time, note, recorded_by, created_at
        FROM %I.attendance
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Daily Logs
      EXECUTE format('
        INSERT INTO public.daily_logs (id, tenant_id, student_id, log_date, log_type, data, recorded_by, created_at)
        SELECT id, %L, student_id, date,
               CASE WHEN type IN (''MEAL'', ''SLEEP'', ''MEDICINE'', ''NOTE'', ''OBSERVATION'') THEN type::"DailyLogType" ELSE ''NOTE''::"DailyLogType" END,
               data, recorded_by, created_at
        FROM %I.daily_logs
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Messages
      EXECUTE format('
        INSERT INTO public.messages (id, tenant_id, from_user_id, to_user_id, body, is_read, sent_at)
        SELECT id, %L, sender_id, receiver_id, body, is_read, created_at
        FROM %I.messages
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Invoices
      EXECUTE format('
        INSERT INTO public.invoices (id, tenant_id, student_id, title, amount, total_amount, due_date, status, paid_at, notes, created_at, updated_at)
        SELECT id, %L, student_id, COALESCE(description, ''Aylık Ödeme''), amount, amount, COALESCE(due_date, CURRENT_DATE), 
               CASE WHEN status IN (''PENDING'', ''PAID'', ''OVERDUE'', ''CANCELLED'') THEN status::"InvoiceStatus" ELSE ''PENDING''::"InvoiceStatus" END,
               paid_at, description, created_at, updated_at
        FROM %I.invoices
        ON CONFLICT (id) DO NOTHING
      ', t.id, s_name);

      -- Payments (sadece %I → tek argüman s_name; t.id KULLANILMAZ yoksa UUID şema adı sanılır)
      EXECUTE format('
        INSERT INTO public.payments (id, invoice_id, amount, provider, provider_ref, status, created_at)
        SELECT id, invoice_id, amount, COALESCE(provider, ''iyzico''), provider_ref,
               CASE WHEN status IN (''PENDING'', ''SUCCESS'', ''FAILED'', ''REFUNDED'') THEN status::"PaymentStatus" ELSE ''PENDING''::"PaymentStatus" END,
               created_at
        FROM %I.payments
        ON CONFLICT (id) DO NOTHING
      ', s_name);

      RAISE NOTICE 'Tenant % (%) verileri taşındı', t.slug, s_name;
    END;
  END LOOP;
END $$;

-- ============================================================
-- 20. ESKİ TENANT ŞEMALARINI TEMİZLE (Opsiyonel)
-- Veri migrasyonu başarılı olduktan sonra İSTERSEN aşağıdaki bloğu
-- tek başına SQL Editor'da çalıştırın.
-- DİKKAT: Geri alınamaz.
-- ============================================================
--
-- DO $$
-- DECLARE
--   t RECORD;
--   s_name TEXT;
-- BEGIN
--   FOR t IN SELECT slug FROM public.tenants LOOP
--     s_name := 'tenant_' || REPLACE(t.slug, '-', '_');
--     EXECUTE format('DROP SCHEMA IF EXISTS %I CASCADE', s_name);
--     RAISE NOTICE 'Şema silindi: %', s_name;
--   END LOOP;
-- END $$;
