// backend/prisma/seed.ts
import { PrismaClient } from '@prisma/client';
import { randomUUID } from 'crypto';
import { config } from 'dotenv';
import path from 'path';
import {
  TREATMENT_TYPES,
  LEGACY_TREATMENT_TYPES,
  LAB_WORKFLOW_STEPS,
  PROSTHESIS_TYPES,
  CATALOG_TRANSLATIONS,
  buildProsthesisStepCodes,
} from './catalog-seed-data';

// Load .env when running locally; Docker injects DATABASE_URL via env_file.
if (!process.env.DATABASE_URL) {
  const envPath = path.join(__dirname, '..', '.env');
  console.log('Loading .env from:', envPath);
  config({ path: envPath });
}

if (!process.env.DATABASE_URL) {
  console.error('❌ DATABASE_URL is not set in environment');
  process.exit(1);
}

console.log('✅ DATABASE_URL found:', process.env.DATABASE_URL.substring(0, 30) + '...');

const prisma = new PrismaClient();

async function main() {
  console.log('🌱 Starting seeding...');

  // Test the connection
  await prisma.$connect();
  console.log('✅ Database connected successfully');

  // Create organization types
  await prisma.organizationType.upsert({
    where: { name: 'CLINIC' },
    update: {},
    create: { name: 'CLINIC' },
  });
  console.log('✅ Created clinic type');

  await prisma.organizationType.upsert({
    where: { name: 'LAB' },
    update: {},
    create: { name: 'LAB' },
  });
  console.log('✅ Created lab type');

  // Create plans
  const plans = [
    { name: 'trial', maxUsers: 5, price: 0, features: {} },
    { name: 'Small', maxUsers: 5, price: 150, features: {} },
    { name: 'Medium', maxUsers: 10, price: 250, features: {} },
    { name: 'Large', maxUsers: 15, price: 400, features: {} },
    { name: 'Enterprise', maxUsers: 999999, price: 1000, features: {} },
  ];

  for (const plan of plans) {
    await prisma.plan.upsert({
      where: { name: plan.name },
      update: {},
      create: plan,
    });
  }
  console.log('✅ Created plans');

  // Minimal permission model (confirmed):
  // - Sidebar tabs use READ/EDIT
  // - EDIT implies READ in app logic
  // - Owners effectively get all permissions
  const features = [
    {
      name: 'Today',
      permissions: ['TAB_TODAY_READ', 'TAB_TODAY_EDIT'],
    },
    {
      name: 'Staff',
      permissions: ['TAB_STAFF_READ', 'TAB_STAFF_EDIT'],
    },
    {
      name: 'Organizations',
      permissions: ['TAB_ORGANIZATIONS_READ', 'TAB_ORGANIZATIONS_EDIT'],
    },
    {
      name: 'Patients',
      permissions: ['TAB_PATIENTS_READ', 'TAB_PATIENTS_EDIT'],
    },
    {
      name: 'Appointment',
      permissions: ['TAB_APPOINTMENTS_READ', 'TAB_APPOINTMENTS_EDIT'],
    },
    {
      name: 'Treatment',
      permissions: ['TAB_TREATMENT_READ', 'TAB_TREATMENT_EDIT'],
    },
    {
      name: 'Cases',
      permissions: ['TAB_CASES_READ', 'TAB_CASES_EDIT'],
    },
    {
      name: 'Tasks',
      permissions: ['TAB_TASKS_READ', 'TAB_TASKS_EDIT'],
    },
    {
      name: 'Billing',
      permissions: ['TAB_BILLING_READ', 'TAB_BILLING_EDIT'],
    },
    {
      name: 'Reports',
      permissions: ['TAB_REPORTS_READ', 'TAB_REPORTS_EDIT'],
    },
  ];

  for (const feature of features) {
    const createdFeature = await prisma.feature.upsert({
      where: { name: feature.name },
      update: {},
      create: { name: feature.name },
    });

    for (const permissionName of feature.permissions) {
      await prisma.permission.upsert({
        where: { name: permissionName },
        update: {},
        create: {
          name: permissionName,
          featureId: createdFeature.id,
        },
      });
    }
  }
  console.log('✅ Created features and permissions');

  for (const type of [...TREATMENT_TYPES, ...LEGACY_TREATMENT_TYPES]) {
    const isActive = TREATMENT_TYPES.some((t) => t.code === type.code);
    const availableInAppointments = type.availableInAppointments ?? true;
    const availableInTreatment = type.availableInTreatment ?? true;
    await prisma.treatmentType.upsert({
      where: { code: type.code },
      update: {
        labDependent: type.labDependent,
        sortOrder: type.sortOrder,
        isActive,
        availableInAppointments,
        availableInTreatment,
      },
      create: {
        id: randomUUID(),
        code: type.code,
        labDependent: type.labDependent,
        sortOrder: type.sortOrder,
        isActive,
        availableInAppointments,
        availableInTreatment,
      },
    });
  }
  console.log('✅ Seeded treatment type catalog');

  for (const step of LAB_WORKFLOW_STEPS) {
    await prisma.labWorkflowStep.upsert({
      where: { code: step.code },
      update: { sortOrder: step.sortOrder },
      create: {
        id: randomUUID(),
        code: step.code,
        sortOrder: step.sortOrder,
      },
    });
  }
  console.log('✅ Seeded lab workflow steps');

  const workflowStepByCode = new Map(
    (
      await prisma.labWorkflowStep.findMany({
        select: { id: true, code: true },
      })
    ).map((s) => [s.code, s.id]),
  );

  for (const type of PROSTHESIS_TYPES) {
    const treeFields = {
      sortOrder: type.sortOrder,
      skipPackingShipping: type.skipPackingShipping ?? false,
      isActive: type.isActive ?? true,
      category: type.category,
      subcategory: type.subcategory ?? '',
      chartRegion: type.chartRegion,
      stackGroup: type.stackGroup,
    };
    const prosthesisType = await prisma.prosthesisType.upsert({
      where: { code: type.code },
      update: treeFields,
      create: {
        id: randomUUID(),
        code: type.code,
        ...treeFields,
      },
    });

    await prisma.prosthesisTypeStep.deleteMany({
      where: { prosthesisTypeId: prosthesisType.id },
    });

    const stepCodes = buildProsthesisStepCodes(type);
    for (const [index, stepCode] of stepCodes.entries()) {
      const labWorkflowStepId = workflowStepByCode.get(stepCode);
      if (!labWorkflowStepId) {
        throw new Error(`Unknown workflow step code: ${stepCode}`);
      }

      await prisma.prosthesisTypeStep.create({
        data: {
          id: randomUUID(),
          prosthesisTypeId: prosthesisType.id,
          labWorkflowStepId,
          stepOrder: index + 1,
        },
      });
    }
  }
  console.log('✅ Seeded prosthesis types and workflow mappings');

  for (const tr of CATALOG_TRANSLATIONS) {
    const existing = await prisma.catalogTranslation.findFirst({
      where: {
        entityKind: tr.entityKind,
        entityCode: tr.entityCode,
        locale: tr.locale,
      },
    });

    if (existing) {
      await prisma.catalogTranslation.update({
        where: { id: existing.id },
        data: { label: tr.label },
      });
    } else {
      await prisma.catalogTranslation.create({
        data: {
          id: randomUUID(),
          entityKind: tr.entityKind,
          entityCode: tr.entityCode,
          locale: tr.locale,
          label: tr.label,
        },
      });
    }
  }
  console.log('✅ Seeded catalog translations');

  console.log('🌱 Seeding completed successfully!');
}

main()
  .catch((e) => {
    console.error('❌ Seeding failed:', e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
