// prisma/seeds/DemographicsSeeder.ts

import { PrismaClient } from '@prisma/client';
import path from 'path';
import XLSX from 'xlsx';

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

  async run(): Promise<void> {
    console.log('📥 Seeding demographics data from Excel...');

    // Clear existing data
    await this.prisma.demographics.deleteMany({});

    const districts = await this.prisma.districts.findMany();
    // await this.prisma.$executeRaw`TRUNCATE TABLE "demographics" CASCADE`;

    // Load Excel
    const filePath = path.join(
      __dirname,
      '../data/excels/administrations/demographics.xlsx'
    );
    const workbook = XLSX.readFile(filePath);
    const sheet = workbook.Sheets[workbook.SheetNames[0]];
    const data = XLSX.utils.sheet_to_json(sheet) as any[];

    let counter = 0;

    for (const row of data) {
      const districtName = String(row['Kecamatan']).trim();
      const year = Number(row['Tahun']);
      const population = Number(row['Jumlah_Penduduk']);
      const unemployed = Number(row['Jumlah_Pengangguran']);

      const district = districts.find(
        (d) => d.name.toLowerCase() === districtName.toLowerCase()
      );

      if (!district) {
        console.warn(`⚠️ District "${districtName}" not found in database.`);
        continue;
      }

      const districtLandArea = await this.getDistrictLandArea(district.id);

      const populationDensity =
        districtLandArea > 0 ? population / districtLandArea : 0;

      await this.prisma.demographics.create({
        data: {
          district_id: district.id,
          year,
          population,
          population_density: populationDensity,
          number_of_unemployed: unemployed,
        },
      });

      counter++;

      console.log(
        `Seeding demographic data for district: ${districtName}, year: ${year}`
      );
    }

    console.log(`✅ ${counter} demographic records seeded from Excel`);
  }

  private getRandomNumber(min: number, max: number): number {
    return Math.random() * (max - min) + min;
  }

  private async getDistrictLandArea(districtId: string): Promise<number> {
    const geo = await this.prisma.geographics.findFirst({
      where: { district_id: districtId },
      select: {
        land_area: true,
      },
    });

    if (!geo) {
      console.error(`⚠️ Land area not found for district ID: ${districtId}`);
      return 0;
    }

    return geo.land_area || 0;
  }

  private async getCityLandArea(): Promise<number> {
    const districtsGeo = await this.prisma.locations.findMany({});
    return districtsGeo.reduce((sum, geo) => sum + (geo.land_area || 0), 0);
  }
}
