/**
 * Data migration script for existing deployments upgrading to v2.
 *
 * Run with: npx tsx prisma/seed-migration.ts
 *
 * This script:
 * 1. Creates a SystemConfig singleton (setup complete)
 * 2. Creates a default Organization from existing data
 * 3. Creates a default Location
 * 4. Creates a default "Sunday Service" CollectionDay
 * 5. Migrates existing Users into OrgMembers
 * 6. Backfills organizationId and locationId on ResponseCards
 * 7. Backfills collectionDayId using existing dates
 */

import "dotenv/config";
import { PrismaClient } from "../src/generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import pg from "pg";

const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });

async function main() {
  console.log("Starting v2 data migration...\n");

  // 1. SystemConfig
  const existingConfig = await prisma.systemConfig.findUnique({
    where: { id: "singleton" },
  });

  if (existingConfig?.isSetupComplete) {
    console.log("Setup already marked complete. Skipping migration.");
    return;
  }

  await prisma.systemConfig.upsert({
    where: { id: "singleton" },
    update: { isSetupComplete: true, setupStep: 3 },
    create: { id: "singleton", isSetupComplete: true, setupStep: 3 },
  });
  console.log("[1/7] SystemConfig created (setup complete)");

  // 2. Default Organization
  let org = await prisma.organization.findFirst();
  if (!org) {
    org = await prisma.organization.create({
      data: {
        name: "My Church",
        slug: "my-church",
        type: "church",
        timezone: "America/Chicago",
      },
    });
    console.log(`[2/7] Created default organization: ${org.name} (${org.id})`);
  } else {
    console.log(`[2/7] Organization already exists: ${org.name}`);
  }

  // 3. Default Location
  let location = await prisma.location.findFirst({
    where: { organizationId: org.id },
  });
  if (!location) {
    location = await prisma.location.create({
      data: {
        name: "Main Campus",
        organizationId: org.id,
      },
    });
    console.log(`[3/7] Created default location: ${location.name} (${location.id})`);
  } else {
    console.log(`[3/7] Location already exists: ${location.name}`);
  }

  // 4. Default CollectionDay
  let collectionDay = await prisma.collectionDay.findFirst({
    where: { locationId: location.id },
  });
  if (!collectionDay) {
    collectionDay = await prisma.collectionDay.create({
      data: {
        locationId: location.id,
        name: "Sunday Service",
        dayOfWeek: 0,
        timeStart: "09:00",
        timeEnd: "12:00",
        isRecurring: true,
      },
    });
    console.log(`[4/7] Created default collection day: ${collectionDay.name}`);
  } else {
    console.log(`[4/7] Collection day already exists: ${collectionDay.name}`);
  }

  // 5. Migrate Users to OrgMembers
  const users = await prisma.user.findMany();
  let memberCount = 0;
  for (const user of users) {
    const existing = await prisma.orgMember.findUnique({
      where: {
        userId_organizationId: {
          userId: user.id,
          organizationId: org.id,
        },
      },
    });
    if (!existing) {
      await prisma.orgMember.create({
        data: {
          userId: user.id,
          organizationId: org.id,
          role: user.role || "viewer",
        },
      });
      memberCount++;
    }
  }
  console.log(`[5/7] Migrated ${memberCount} users to org members (${users.length} total users)`);

  // 6. Backfill ResponseCard.organizationId and locationId
  const cardResult = await prisma.responseCard.updateMany({
    where: { organizationId: null },
    data: {
      organizationId: org.id,
      locationId: location.id,
    },
  });
  console.log(`[6/7] Backfilled ${cardResult.count} cards with org/location`);

  // 7. Backfill collectionDayId
  const cardsWithDates = await prisma.responseCard.findMany({
    where: {
      collectionDayId: null,
      OR: [
        { firstTimeGuestDate: { not: null } },
        { createdAt: { not: undefined } },
      ],
    },
    select: { id: true, firstTimeGuestDate: true, createdAt: true },
  });

  let assignedCount = 0;
  for (const card of cardsWithDates) {
    const refDate = card.firstTimeGuestDate || card.createdAt;
    const sunday = new Date(refDate);
    const day = sunday.getDay();
    if (day !== 0) sunday.setDate(sunday.getDate() - day);
    sunday.setHours(0, 0, 0, 0);

    await prisma.responseCard.update({
      where: { id: card.id },
      data: {
        collectionDayId: collectionDay.id,
        collectionDate: sunday,
      },
    });
    assignedCount++;
  }
  console.log(`[7/7] Assigned ${assignedCount} cards to default collection day`);

  // 8. Backfill ProcessingJob.organizationId
  await prisma.processingJob.updateMany({
    where: { organizationId: null },
    data: { organizationId: org.id },
  });

  console.log("\nMigration complete!");
}

main()
  .catch((e) => {
    console.error("Migration failed:", e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
    await pool.end();
  });
