import { db } from "./connection";
import { employees, branches } from "./schema";
import { eq } from "drizzle-orm";
import * as fs from "fs";
import * as path from "path";
import * as readline from "readline";

// Path to CSV file
const CSV_PATH = path.join(process.cwd(), "alla-emp.csv");

// Parse CSV line and return employee object
function parseCSVLine(
  line: string,
): {
  id: string;
  employeeId: string;
  name: string;
  branchId: string;
  pin: string;
} | null {
  const parts = line.split(",");
  if (parts.length < 5) return null;

  const id = parts[0].trim();
  const employeeId = parts[1].trim();
  const name = parts[2].trim();
  const branchId = parts[3].trim();
  const pin = parts[4].trim();

  if (!id || !employeeId || !name || !branchId || !pin) {
    return null;
  }

  return { id, employeeId, name, branchId, pin };
}

// Read CSV file and parse all lines
async function readCSV(filePath: string): Promise<any[]> {
  return new Promise((resolve, reject) => {
    const results: any[] = [];
    const fileStream = fs.createReadStream(filePath);

    const rl = readline.createInterface({
      input: fileStream,
      crlfDelay: Infinity,
    });

    let isFirstLine = true;

    rl.on("line", (line) => {
      // Skip header line
      if (isFirstLine) {
        isFirstLine = false;
        return;
      }

      const parsed = parseCSVLine(line);
      if (parsed) {
        results.push(parsed);
      }
    });

    rl.on("close", () => {
      resolve(results);
    });

    rl.on("error", (err) => {
      reject(err);
    });
  });
}

async function seedEmployees() {
  console.log("🌱 Seeding employees from CSV...");
  console.log(`📄 Reading CSV file: ${CSV_PATH}`);

  // Check if CSV file exists
  if (!fs.existsSync(CSV_PATH)) {
    console.error("❌ CSV file not found:", CSV_PATH);
    console.error(
      "   Please make sure alla-emp.csv is in the project root directory.",
    );
    process.exit(1);
  }

  // Read and parse CSV
  let employeeData: any[];
  try {
    employeeData = await readCSV(CSV_PATH);
    console.log(`✅ Parsed ${employeeData.length} employees from CSV`);
  } catch (error) {
    console.error("❌ Error reading CSV file:", error);
    process.exit(1);
  }

  if (employeeData.length === 0) {
    console.log("⚠️  No employees found in CSV file");
    return;
  }

  // Get unique branch IDs from CSV
  const uniqueBranchIds = [...new Set(employeeData.map((emp) => emp.branchId))];
  console.log(`🏢 Found ${uniqueBranchIds.length} unique branches in CSV`);

  // Check if all branches exist in database
  console.log("🔍 Checking branches in database...");
  const existingBranches = await db.select().from(branches);
  const existingBranchIds = existingBranches.map((b) => b.id);

  const missingBranches = uniqueBranchIds.filter(
    (id) => !existingBranchIds.includes(id),
  );

  if (missingBranches.length > 0) {
    console.error("❌ Missing branches in database:");
    missingBranches.forEach((branchId) => {
      console.error(`   - ${branchId}`);
    });
    console.error(
      "\n❌ Please run seed.ts first to create branches, or add the missing branches manually.",
    );
    console.error(`   Existing branches: ${existingBranchIds.join(", ")}`);
    process.exit(1);
  }

  console.log(`✅ All ${uniqueBranchIds.length} branches found in database`);

  // Check if employees already exist (to avoid duplicates)
  console.log("🔍 Checking for existing employees...");
  const existingEmployees = await db.select().from(employees);
  const existingEmployeeIds = new Set(existingEmployees.map((e) => e.id));

  const newEmployees = employeeData.filter(
    (emp) => !existingEmployeeIds.has(emp.id),
  );

  if (newEmployees.length === 0) {
    console.log(
      "⏭️  All employees from CSV already exist in database. Skipping...",
    );
    return;
  }

  console.log(`📝 Found ${newEmployees.length} new employees to insert`);

  // Insert employees in batches
  const BATCH_SIZE = 50;
  let insertedCount = 0;
  let errorCount = 0;

  for (let i = 0; i < newEmployees.length; i += BATCH_SIZE) {
    const batch = newEmployees.slice(i, i + BATCH_SIZE);

    for (const emp of batch) {
      try {
        await db.insert(employees).values({
          id: emp.id,
          employeeId: emp.employeeId,
          name: emp.name,
          branchId: emp.branchId,
          isAdmin: false,
          pin: emp.pin,
          isActive: true,
        });
        insertedCount++;
      } catch (error) {
        console.error(
          `❌ Error inserting employee ${emp.employeeId} (${emp.name}):`,
          error,
        );
        errorCount++;
      }
    }

    // Progress indicator
    const progress = Math.min(i + BATCH_SIZE, newEmployees.length);
    console.log(
      `   Progress: ${progress}/${newEmployees.length} employees processed`,
    );
  }

  // Final report
  console.log("\n🎉 Employee seeding complete!");
  console.log(`   ✅ Successfully inserted: ${insertedCount} employees`);
  if (errorCount > 0) {
    console.log(`   ❌ Failed to insert: ${errorCount} employees`);
  }
  console.log(
    `   📊 Total employees in database: ${insertedCount + existingEmployees.length}`,
  );
}

// Run the seed
seedEmployees().catch((error) => {
  console.error("❌ Fatal error during seeding:", error);
  process.exit(1);
});
