import fs from 'fs';
import path from 'path';
import { parse } from 'csv-parse';
import { Types } from 'mongoose';

import Country from '@/modules/master/location/country/country.model';
import State from '@/modules/master/location/state/state.model';
import City from '@/modules/master/location/city/city.model';
import Area from '@/modules/master/location/area/area.model';

interface IAndhraPradeshCity {
  name: string;
  lat: number;
  long: number;
  stateName: string;
}

interface IAndhraPradeshAreaRecord {
  Area: string;
  City: string;
  StateName: string;
  Pincode: string;
  Latitude: string;
  Longitude: string;
  'State Latitude': string;
  'State Longitude': string;
}

// Function to escape special regex characters
function escapeRegex(string: string): string {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

export const seedAndhraPradeshUnified = async ({
  superAdminId,
}: {
  superAdminId: string | Types.ObjectId;
}) => {
  try {
    console.log('🔄 Starting unified Andhra Pradesh seeding...');

    // First, find or create the India country document
    let countryDoc = await Country.findOne({ name: 'india' });
    if (!countryDoc) {
      countryDoc = await Country.create({
        name: 'india',
        code: 'IN',
        loc: {
          type: 'Point',
          coordinates: [77.00000000, 20.00000000], // [longitude, latitude]
        },
        createdBy: superAdminId,
        updatedBy: superAdminId,
      });
      console.log('✅ India country created');
    } else {
      console.log('✅ India country found');
    }

    // Check if Andhra Pradesh state already exists
    const existingState = await State.findOne({ name: 'andhra pradesh' });
    let stateDoc;
    if (existingState) {
      stateDoc = existingState;
      console.log('⚠️ Andhra Pradesh state already exists, using existing document');
    } else {
      // Create Andhra Pradesh state
      stateDoc = await State.create({
        name: 'andhra pradesh',
        country: countryDoc._id,
        loc: {
          type: 'Point',
          coordinates: [79.60000000, 15.80000000], // [longitude, latitude] - approximate center
        },
        createdBy: superAdminId,
        updatedBy: superAdminId,
      });
      console.log('✅ Andhra Pradesh state created');
    }

    // STEP 1: Seed cities from cities.json
    console.log('🔄 Seeding cities from cities.json...');
    // Read the cities data from the JSON file
    const jsonPath = path.join(
      process.cwd(),
      'src/shared/seeder/location/Andhra Pradesh/cities.json'
    );

    const citiesData = JSON.parse(fs.readFileSync(jsonPath, 'utf-8')) as IAndhraPradeshCity[];

    if (Array.isArray(citiesData) && citiesData.length > 0) {
      const citiesPayload = citiesData.map((city: IAndhraPradeshCity) => ({
        name: String(city.name).toLowerCase(),
        state: stateDoc._id,
        loc: {
          type: 'Point',
          coordinates: [
            Number(city.long || 0), // longitude
            Number(city.lat || 0),   // latitude
          ],
        },
        createdBy: superAdminId,
        updatedBy: superAdminId,
      }));

      // Insert cities, skipping duplicates
      let insertedCityCount = 0;
      for (const cityPayload of citiesPayload) {
        const existingCity = await City.findOne({ 
          name: { $regex: new RegExp(`^${escapeRegex(cityPayload.name)}$`, 'i') },
          state: stateDoc._id 
        });
        if (!existingCity) {
          await City.create(cityPayload);
          insertedCityCount++;
        }
      }

      console.log(`✅ ${insertedCityCount} cities from Andhra Pradesh inserted successfully`);
      console.log(`📊 Total cities in Andhra Pradesh: ${citiesData.length}`);
    } else {
      console.log('⚠️ No cities data found in the Andhra Pradesh JSON file');
    }

    // STEP 2: Seed areas from ANDHRA PRADESH.csv
    console.log('🔄 Seeding areas from ANDHRA PRADESH.csv...');

    // Read and parse the CSV file
    const csvPath = path.join(
      process.cwd(),
      'src/shared/seeder/location/Andhra Pradesh/ANDHRA PRADESH.csv'
    );

    const csvContent = fs.readFileSync(csvPath, 'utf-8');

    // Parse CSV data
    const records: IAndhraPradeshAreaRecord[] = [];

    await new Promise<void>((resolve, reject) => {
      const parser = parse({
        columns: true,
        skip_empty_lines: true,
      });
      parser.on('readable', () => {
        let record;
        while ((record = parser.read()) !== null) {
          records.push(record as IAndhraPradeshAreaRecord);
        }
      });
      parser.on('error', (err) => {
        console.error('Error parsing CSV:', err);
        reject(err);
      });

      parser.on('end', () => {
        resolve();
      });

      parser.write(csvContent);
      parser.end();
    });

    console.log(`📊 Found ${records.length} area records to process`);

    let processedCount = 0;
    let createdCount = 0;

    // Process each record
    for (const record of records) {
      // Find or create the city
      const cityName = record.City.toLowerCase();
      let cityDoc = await City.findOne({ 
        name: { $regex: new RegExp(`^${escapeRegex(cityName)}$`, 'i') }, 
        state: stateDoc._id 
      });
      if (!cityDoc) {
        // Create city if it doesn't exist
        // Use state coordinates as fallback if available
        const stateLongitude = parseFloat(record['State Longitude']) || 79.74;
        const stateLatitude = parseFloat(record['State Latitude']) || 15.9129;
        cityDoc = await City.create({
          name: cityName,
          state: stateDoc._id,
          loc: {
            type: 'Point',
            coordinates: [
              stateLongitude, // longitude
              stateLatitude,  // latitude
            ],
          },
          createdBy: superAdminId,
          updatedBy: superAdminId,
        });
        console.log(`✅ Created city: ${cityName}`);
      }

      // Process area data
      const areaName = record.Area.trim().toLowerCase();
      const pincode = parseInt(record.Pincode, 10);
      const latitude = parseFloat(record.Latitude);
      const longitude = parseFloat(record.Longitude);

      // Validate coordinates
      if (isNaN(latitude) || isNaN(longitude)) {
        console.warn(`⚠️ Skipping area ${areaName} due to invalid coordinates`);
        continue;
      }

      // Check if area already exists
      const existingArea = await Area.findOne({
        name: { $regex: new RegExp(`^${escapeRegex(areaName)}$`, 'i') },
        city: cityDoc._id
      });

      if (!existingArea) {
        await Area.create({
          name: areaName,
          city: cityDoc._id,
          pinCode: [pincode],
          loc: {
            type: 'Point',
            coordinates: [longitude, latitude], // [longitude, latitude]
          },
          createdBy: superAdminId,
          updatedBy: superAdminId,
        });
        createdCount++;
      }

      processedCount++;
      if (processedCount % 500 === 0) {
        console.log(`🔄 Processed ${processedCount}/${records.length} areas...`);
      }
    }

    console.log(`✅ Andhra Pradesh unified seeding completed!`);
    console.log(`📊 Cities processed: ${citiesData.length}, Areas processed: ${processedCount}, Areas created: ${createdCount}`);
  } catch (err) {
    console.log('❌ Error in unified seeding Andhra Pradesh data', err);
    throw err;
  }
};