const { PrismaClient } = require('@prisma/client');
const { PrismaPg } = require('@prisma/adapter-pg');
const { Pool } = require('pg');
require('dotenv').config();

const dbUrl = new URL(process.env.DATABASE_URL_WALKTHROUGH || "postgresql://special_hotel_user:SpecialHotel1235%2F%2A-%2B@pg.gaboggamer.online/special_hotel_walkthrough?schema=public");

const pool = new Pool({
  host: dbUrl.hostname,
  port: dbUrl.port ? parseInt(dbUrl.port) : 5432,
  user: decodeURIComponent(dbUrl.username),
  password: decodeURIComponent(dbUrl.password),
  database: dbUrl.pathname.substring(1).split('?')[0],
  ssl: false
});

const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });

const PASSWORD_HASH = '$2b$10$lRn/GrwzaEGxWqqQGGz0f.44nBywObKkGWRajlxWeDGZ3o4f7ayjy'; // bcrypt of 'password123'

async function main() {
  console.log("=== STARTING WALKTHROUGH SEED SCRIPT ===");

  // 1. Clean existing records in the walkthrough database to ensure clean seeding
  console.log("Cleaning database...");
  // Disable RLS temporarily for bulk seed operations
  await prisma.$executeRawUnsafe(`ALTER TABLE "regions" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "hotels" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "users" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "goals" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "sales_results" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "settlements" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "audit_logs" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "compensation_plans" DISABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "calculation_rules" DISABLE ROW LEVEL SECURITY;`);

  await prisma.auditLog.deleteMany();
  await prisma.notification.deleteMany();
  await prisma.settlement.deleteMany();
  await prisma.salesResult.deleteMany();
  await prisma.goal.deleteMany();
  await prisma.calculationRule.deleteMany();
  await prisma.compensationPlan.deleteMany();
  await prisma.user.deleteMany();
  await prisma.hotel.deleteMany();
  await prisma.region.deleteMany();

  // 2. Seed Regions
  console.log("Seeding regions...");
  const bogota = await prisma.region.create({ data: { name: 'Bogotá', code: 'BOG' } });
  const antioquia = await prisma.region.create({ data: { name: 'Antioquia', code: 'ANT' } });
  const caribe = await prisma.region.create({ data: { name: 'Caribe', code: 'CAR' } });
  const valle = await prisma.region.create({ data: { name: 'Valle', code: 'VAL' } });

  // 3. Seed Hotels
  console.log("Seeding hotels...");
  const p93 = await prisma.hotel.create({ data: { name: 'Estelar Parque de la 93', code: 'EST-P93', regionId: bogota.id } });
  const mde = await prisma.hotel.create({ data: { name: 'Estelar Medellin', code: 'EST-MDE', regionId: antioquia.id } });
  const ctg = await prisma.hotel.create({ data: { name: 'Estelar Cartagena', code: 'EST-CTG', regionId: caribe.id } });
  const cali = await prisma.hotel.create({ data: { name: 'Estelar Cali', code: 'EST-CALI', regionId: valle.id } });

  // 4. Seed Users
  console.log("Seeding users...");
  const usersToSeed = [
    { username: 'admin', email: 'admin@estelar.com', role: 'admin', hotelId: p93.id, area: 'Sistemas' },
    { username: 'director', email: 'director@estelar.com', role: 'director', hotelId: p93.id, area: 'Comercial' },
    { username: 'analista', email: 'analista@estelar.com', role: 'analyst', hotelId: p93.id, area: 'Finanzas' },
    { username: 'consulta', email: 'consulta@estelar.com', role: 'auditor', hotelId: p93.id, area: 'Auditoria' },
    
    // Managers
    { username: 'gerente_bog', email: 'gerente.bog@estelar.com', role: 'hotel_manager', hotelId: p93.id, area: 'Administracion' },
    { username: 'gerente_mde', email: 'gerente.mde@estelar.com', role: 'hotel_manager', hotelId: mde.id, area: 'Administracion' },
    { username: 'gerente_ctg', email: 'gerente.ctg@estelar.com', role: 'hotel_manager', hotelId: ctg.id, area: 'Administracion' },
    { username: 'gerente_cali', email: 'gerente.cali@estelar.com', role: 'hotel_manager', hotelId: cali.id, area: 'Administracion' },

    // Leaders
    { username: 'lider_bog', email: 'lider.bog@estelar.com', role: 'commercial_leader', hotelId: p93.id, area: 'Ventas' },
    { username: 'lider_mde', email: 'lider.mde@estelar.com', role: 'commercial_leader', hotelId: mde.id, area: 'Ventas' },
    { username: 'lider_ctg', email: 'lider.ctg@estelar.com', role: 'commercial_leader', hotelId: ctg.id, area: 'Ventas' },
    { username: 'lider_cali', email: 'lider.cali@estelar.com', role: 'commercial_leader', hotelId: cali.id, area: 'Ventas' },

    // Collaborators
    { username: 'colab_bog_1', email: 'colab.bog1@estelar.com', role: 'collaborator', hotelId: p93.id, area: 'Ventas' },
    { username: 'colab_bog_2', email: 'colab.bog2@estelar.com', role: 'collaborator', hotelId: p93.id, area: 'Ventas' },
    { username: 'colab_mde_1', email: 'colab.mde1@estelar.com', role: 'collaborator', hotelId: mde.id, area: 'Ventas' },
    { username: 'colab_mde_2', email: 'colab.mde2@estelar.com', role: 'collaborator', hotelId: mde.id, area: 'Ventas' },
    { username: 'colaborador_mde', email: 'colaborador.mde@estelar.com', role: 'collaborator', hotelId: mde.id, area: 'Ventas' },
    { username: 'colab_ctg_1', email: 'colab.ctg1@estelar.com', role: 'collaborator', hotelId: ctg.id, area: 'Ventas' },
    { username: 'colab_ctg_2', email: 'colab.ctg2@estelar.com', role: 'collaborator', hotelId: ctg.id, area: 'Ventas' },
    { username: 'colab_cali_1', email: 'colab.cali1@estelar.com', role: 'collaborator', hotelId: cali.id, area: 'Ventas' },
    { username: 'colab_cali_2', email: 'colab.cali2@estelar.com', role: 'collaborator', hotelId: cali.id, area: 'Ventas' }
  ];

  const seededUsers = {};
  for (const u of usersToSeed) {
    const created = await prisma.user.create({
      data: {
        username: u.username,
        email: u.email,
        passwordHash: PASSWORD_HASH,
        role: u.role,
        hotelId: u.hotelId,
        area: u.area,
        status: 'ACTIVE'
      }
    });
    seededUsers[u.username] = created;
  }

  // 5. Seed Compensation Plans & Rules
  console.log("Seeding compensation plans...");
  // Plan Q1 (Percentage, Inactive)
  const planQ1 = await prisma.compensationPlan.create({
    data: {
      name: 'Plan Comisiones Q1 - Porcentaje Fijo',
      code: 'PLAN-2026-Q1',
      validityStart: new Date('2026-01-01'),
      validityEnd: new Date('2026-03-31'),
      type: 'PERCENTAGE',
      percentageRate: 0.025, // 2.5%
      maxCap: 15000.00,
      status: 'INACTIVE',
      version: 1,
      createdBy: seededUsers['admin'].id
    }
  });

  // Plan Q2 (Scale, Active)
  const planQ2 = await prisma.compensationPlan.create({
    data: {
      name: 'Plan Comisiones Q2 - Escala Escalonada',
      code: 'PLAN-2026-Q2',
      validityStart: new Date('2026-04-01'),
      validityEnd: new Date('2026-06-30'),
      type: 'SCALE',
      status: 'ACTIVE',
      version: 1,
      createdBy: seededUsers['admin'].id
    }
  });

  // Calculation rules for Q2 Plan
  console.log("Seeding calculation rules...");
  await prisma.calculationRule.createMany({
    data: [
      { planId: planQ2.id, type: 'TIER', minAchievement: 0.0, maxAchievement: 0.8, rate: 0.0, payoutAmount: 0.0 },
      { planId: planQ2.id, type: 'TIER', minAchievement: 0.8, maxAchievement: 1.0, rate: 0.02, payoutAmount: 100.0 },
      { planId: planQ2.id, type: 'TIER', minAchievement: 1.0, maxAchievement: 9.9, rate: 0.03, payoutAmount: 250.0 }
    ]
  });

  // 6. Seed Goals, Sales Results and Settlements
  console.log("Seeding goals, sales, and settlements...");
  const collaborators = [
    'colab_bog_1', 'colab_bog_2',
    'colab_mde_1', 'colab_mde_2', 'colaborador_mde',
    'colab_ctg_1', 'colab_ctg_2',
    'colab_cali_1', 'colab_cali_2'
  ];

  const periods = ['2026-01', '2026-02', '2026-03', '2026-04', '2026-05', '2026-06'];

  // Seed structured sales, goals and settlements month-by-month
  for (const period of periods) {
    const isQ2 = period >= '2026-04';
    const plan = isQ2 ? planQ2 : planQ1;

    for (const username of collaborators) {
      const user = seededUsers[username];
      
      // Goal Setup
      let goalAmount = 70000.00;
      if (username.endsWith('2')) goalAmount = 60000.00;
      if (username === 'colaborador_mde') goalAmount = 80000.00;
      
      // Random variance for each user and month
      const hashVal = (username.length + period.charCodeAt(6)) % 10;
      const achievementMultiplier = 0.75 + (hashVal * 0.04); // ranges from 0.75 to 1.15
      const salesAmount = goalAmount * achievementMultiplier;

      // Create Goal
      const goal = await prisma.goal.create({
        data: {
          targetType: 'INDIVIDUAL',
          targetId: user.id,
          period,
          amount: goalAmount
        }
      });

      // Create Sales Entries
      const entryCount = 4;
      const amountPerEntry = salesAmount / entryCount;
      const salesCountPerEntry = Math.round(5 + hashVal / 2);

      for (let i = 0; i < entryCount; i++) {
        // Build unique idempotency key
        const idempotencyKey = `sale-${user.id}-${period}-${i}`;

        // Seed normal sale
        await prisma.salesResult.create({
          data: {
            source: 'EXCEL',
            hotelId: user.hotelId,
            userId: user.id,
            period,
            amount: amountPerEntry,
            salesCount: salesCountPerEntry,
            status: 'PROCESSED',
            idempotencyKey,
            uploadedBy: seededUsers['gerente_mde'].id, // Seed uploaded by MDE manager for convenience
            isAnomaly: false
          }
        });
      }

      // Add a flagged outlier anomaly for colab_bog_1 in March
      if (username === 'colab_bog_1' && period === '2026-03') {
        await prisma.salesResult.create({
          data: {
            source: 'EXCEL',
            hotelId: user.hotelId,
            userId: user.id,
            period,
            amount: 85000.00,
            salesCount: 45,
            status: 'PROCESSED',
            idempotencyKey: `anomaly-outlier-bog1-mar`,
            uploadedBy: seededUsers['gerente_bog'].id,
            isAnomaly: true,
            flaggedReason: {
              en: "Outlier transaction: Sale amount exceeds standard region limits.",
              es: "Transacción atípica: El monto de venta supera los límites regionales estándar."
            }
          }
        });
      }

      // Compute Commission & Bonus
      let commission = 0;
      let bonus = 0;
      const achievement = salesAmount / goalAmount;

      if (!isQ2) {
        // Percentage plan: 2.5% of total sales
        commission = salesAmount * 0.025;
        bonus = 0;
      } else {
        // Scale plan rules
        if (achievement >= 0.8 && achievement < 1.0) {
          commission = salesAmount * 0.02;
          bonus = 100.00;
        } else if (achievement >= 1.0) {
          commission = salesAmount * 0.03;
          bonus = 250.00;
        }
      }

      // Retroactive Clawback deduction for colab_mde_1 in May 2026
      let adjustmentAmount = 0.00;
      let adjustmentNotes = null;
      let originalSettlementId = null;

      if (username === 'colab_mde_1' && period === '2026-05') {
        // Clawback applied for returned sale of $15000 in March 2026 (PLAN Q1 rate: 2.5%)
        adjustmentAmount = -375.00; 
        adjustmentNotes = "Deducción de retroactivo: Devolución de reserva de ventas de marzo (PLAN-2026-Q1).";
        
        // Find their March settlement to link as original
        const marchSettlement = await prisma.settlement.findFirst({
          where: { userId: user.id, period: '2026-03' }
        });
        if (marchSettlement) {
          originalSettlementId = marchSettlement.id;
        }
      }

      const totalPayout = commission + bonus + adjustmentAmount;

      // Settlement Status: APPROVED for Jan-May, PENDING for June
      const isJune = period === '2026-06';
      const settlementStatus = isJune ? 'PENDING' : 'APPROVED';

      const managerMap = {
        [p93.id]: seededUsers['gerente_bog'].id,
        [mde.id]: seededUsers['gerente_mde'].id,
        [ctg.id]: seededUsers['gerente_ctg'].id,
        [cali.id]: seededUsers['gerente_cali'].id
      };

      await prisma.settlement.create({
        data: {
          period,
          planId: plan.id,
          userId: user.id,
          salesAmount,
          goalAmount,
          achievementPercentage: achievement,
          calculatedCommission: commission,
          calculatedBonus: bonus,
          adjustmentAmount,
          totalPayout,
          status: settlementStatus,
          approvedBy: isJune ? null : managerMap[user.hotelId],
          approvedAt: isJune ? null : new Date(`${period}-05T14:30:00Z`),
          originalSettlementId,
          adjustmentNotes,
          aiAudited: true,
          aiAuditNotes: {
            en: isJune 
              ? "Calculated under PLAN-2026-Q2. Validation checks successfully completed." 
              : "Compliant commission settlement. Payout successfully audited.",
            es: isJune 
              ? "Calculado bajo el PLAN-2026-Q2. Revisiones de validación completadas exitosamente."
              : "Liquidación de comisiones conforme. Pago auditado correctamente."
          }
        }
      });
    }
  }

  // 7. Seed Audit Logs Trail
  console.log("Seeding audit logs...");
  const logs = [
    { userId: seededUsers['admin'].id, action: 'LOGIN', targetTable: 'users', targetId: seededUsers['admin'].id, prev: null, next: null, ip: '::1', date: '2026-01-02T09:00:00Z' },
    { userId: seededUsers['admin'].id, action: 'CREATE', targetTable: 'compensation_plans', targetId: planQ1.id, prev: null, next: { id: planQ1.id, code: planQ1.code, status: 'DRAFT' }, ip: '127.0.0.1', date: '2026-01-02T09:15:00Z' },
    { userId: seededUsers['admin'].id, action: 'UPDATE', targetTable: 'compensation_plans', targetId: planQ1.id, prev: { status: 'DRAFT' }, next: { status: 'ACTIVE' }, ip: '127.0.0.1', date: '2026-01-05T10:00:00Z' },
    { userId: seededUsers['gerente_mde'].id, action: 'LOGIN', targetTable: 'users', targetId: seededUsers['gerente_mde'].id, prev: null, next: null, ip: '10.8.0.5', date: '2026-02-05T08:30:00Z' },
    { userId: seededUsers['gerente_mde'].id, action: 'APPROVE', targetTable: 'settlements', targetId: 1, prev: { status: 'PENDING' }, next: { status: 'APPROVED' }, ip: '10.8.0.5', date: '2026-02-05T08:45:00Z' },
    { userId: seededUsers['gerente_bog'].id, action: 'LOGIN', targetTable: 'users', targetId: seededUsers['gerente_bog'].id, prev: null, next: null, ip: '10.8.0.6', date: '2026-02-05T09:12:00Z' },
    { userId: seededUsers['gerente_bog'].id, action: 'APPROVE', targetTable: 'settlements', targetId: 2, prev: { status: 'PENDING' }, next: { status: 'APPROVED' }, ip: '10.8.0.6', date: '2026-02-05T09:18:00Z' }
  ];

  for (const log of logs) {
    await prisma.auditLog.create({
      data: {
        userId: log.userId,
        action: log.action,
        targetTable: log.targetTable,
        targetId: log.targetId,
        previousValue: log.prev,
        newValue: log.next,
        ipAddress: log.ip,
        createdAt: new Date(log.date)
      }
    });
  }

  // 8. Re-enable Row-Level Security Policies via SQL
  console.log("Configuring database RLS boundaries...");
  await prisma.$executeRawUnsafe(`ALTER TABLE "regions" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "hotels" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "users" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "goals" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "sales_results" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "settlements" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "audit_logs" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "compensation_plans" ENABLE ROW LEVEL SECURITY;`);
  await prisma.$executeRawUnsafe(`ALTER TABLE "calculation_rules" ENABLE ROW LEVEL SECURITY;`);

  // Disconnect temporary prisma connection before running manual execute
  await prisma.$disconnect();

  console.log("Walkthrough seeding completed successfully!");
}

main()
  .catch(async (e) => {
    console.error("Error during walkthrough seeding:", e);
    process.exit(1);
  });
