// prisma/seeds/CrimeCategoriesSeeder.ts
import { generateId, generateIdWithDbCounter } from '../../app/_utils/common';
import { PrismaClient } from '@prisma/client';
import { crimeCategoriesData } from '../data/jsons/crime-category';

import path from 'path';
import XLSX from 'xlsx';

interface ICrimeCategory {
  id: string;
  name: string;
  description: string;
  type: string;
  created_at: Date;
  updated_at: Date;
}

export class CrimeCategoriesSeeder {
  constructor(private prisma: PrismaClient) {}

  async run(): Promise<void> {
    console.log('Seeding crime categories...');

    // Hapus data yang ada untuk menghindari duplikasi
    await this.prisma.crime_categories.deleteMany({});

    // Truncate table jika diperlukan
    // await this.prisma.$executeRaw`TRUNCATE TABLE "crime_categories" CASCADE`;

    const filePath = path.join(
      __dirname,
      '../data/excels/others/crime_categories.xlsx'
    );
    const workbook = XLSX.readFile(filePath);
    const sheet = workbook.Sheets[workbook.SheetNames[0]];
    const data = XLSX.utils.sheet_to_json(sheet) as ICrimeCategory[];

    // Prepare array for batch insertion
    const categoriesToCreate = [];

    // Generate IDs and prepare data for batch insertion
    for (const category of crimeCategoriesData) {
      const newId = await generateIdWithDbCounter('crime_categories', {
        prefix: 'CC',
        segments: {
          sequentialDigits: 4,
        },
        format: '{prefix}-{sequence}',
        separator: '-',
        uniquenessStrategy: 'counter',
      });

      categoriesToCreate.push({
        id: newId.trim(),
        name: category.name,
        description: category.description,
      });
    }

    // Batch create categories
    await this.prisma.crime_categories.createMany({
      data: categoriesToCreate,
      skipDuplicates: true,
    });

    console.log(`Batch created ${categoriesToCreate.length} crime categories.`);

    // Prepare data for batch update
    const categoriesToUpdate = data.map((row) => ({
      id: row['id'].trim(),
      type: row['type'].trim(),
      name: row['name'].trim(),
    }));

    // Batch update is not directly supported by Prisma, so we'll use Promise.all with individual updates
    await Promise.all(
      categoriesToUpdate.map((category) =>
        this.prisma.crime_categories.updateMany({
          where: { id: category.id },
          data: { type: category.type },
        })
      )
    );

    console.log(
      `Updated types for ${categoriesToUpdate.length} crime categories.`
    );

    console.log(`✅ ${crimeCategoriesData.length} crime categories seeded`);
  }
}
