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

const dbUrl = new URL(process.env.DATABASE_URL);
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 });

async function runTests() {
  console.log("=== STARTING PHASE 6 RLS INTEGRATION TEST ===");

  // 1. Fetch seeded users (Run as ADMIN role to bypass RLS)
  const { users, plan } = await prisma.$transaction(async (tx) => {
    await tx.$executeRawUnsafe(`SET LOCAL app.current_user_role = 'admin';`);
    const users = await tx.user.findMany({ include: { hotel: true } });
    
    // Ensure we have at least one active compensation plan
    let plan = await tx.compensationPlan.findFirst();
    if (!plan) {
      const adminUser = users.find(u => u.role === 'admin');
      plan = await tx.compensationPlan.create({
        data: {
          name: 'Test Plan',
          code: 'TEST-PLAN',
          validityStart: new Date(),
          type: 'PERCENTAGE',
          status: 'ACTIVE',
          createdBy: adminUser.id
        }
      });
    }
    return { users, plan };
  });

  const adminUser = users.find(u => u.username === 'admin');
  const gerenteMde = users.find(u => u.username === 'gerente_mde');
  const colaboradorMde = users.find(u => u.username === 'colaborador_mde');
  const liderCtg = users.find(u => u.username === 'lider_ctg');

  if (!adminUser || !gerenteMde || !colaboradorMde || !liderCtg) {
    console.error("Error: Could not find all required seeded users.");
    process.exit(1);
  }

  let passed = 0;
  let failed = 0;

  function assert(condition, message) {
    if (condition) {
      console.log(`  ✓ PASS: ${message}`);
      passed++;
    } else {
      console.error(`  ✗ FAIL: ${message}`);
      failed++;
    }
  }

  // Helper to run query with context
  async function runWithContext(user, queryFn) {
    return prisma.$transaction(async (tx) => {
      await tx.$executeRawUnsafe(`SET LOCAL app.current_user_id = '${user.id}';`);
      await tx.$executeRawUnsafe(`SET LOCAL app.current_user_role = '${user.role}';`);
      await tx.$executeRawUnsafe(`SET LOCAL app.current_hotel_id = '${user.hotelId}';`);
      await tx.$executeRawUnsafe(`SET LOCAL app.current_region_id = '${user.hotel.regionId}';`);
      return queryFn(tx);
    });
  }

  let settlementMde, settlementCtg;

  try {
    // 2. Clean up old test settlements
    await runWithContext(adminUser, async (tx) => {
      await tx.settlement.deleteMany({
        where: { period: '2026-99' }
      });
    });

    // 3. Create test settlements (as Admin)
    settlementMde = await runWithContext(adminUser, async (tx) => {
      return tx.settlement.create({
        data: {
          period: '2026-99',
          planId: plan.id,
          userId: colaboradorMde.id,
          salesAmount: 10000.00,
          goalAmount: 8000.00,
          achievementPercentage: 1.25,
          calculatedCommission: 1200.00,
          calculatedBonus: 0,
          adjustmentAmount: 0,
          totalPayout: 1200.00,
          status: 'APPROVED'
        }
      });
    });

    settlementCtg = await runWithContext(adminUser, async (tx) => {
      return tx.settlement.create({
        data: {
          period: '2026-99',
          planId: plan.id,
          userId: liderCtg.id,
          salesAmount: 15000.00,
          goalAmount: 12000.00,
          achievementPercentage: 1.25,
          calculatedCommission: 1800.00,
          calculatedBonus: 0,
          adjustmentAmount: 0,
          totalPayout: 1800.00,
          status: 'APPROVED'
        }
      });
    });

    // 4. Test RLS on Settlements for Colaborador MDE
    const colabSettlements = await runWithContext(colaboradorMde, async (tx) => {
      return tx.settlement.findMany({ where: { period: '2026-99' } });
    });
    assert(
      colabSettlements.length === 1 && colabSettlements[0].id === settlementMde.id,
      "Colaborador MDE can only see their own history record and not Lider CTG's record"
    );

    // 5. Test RLS on Settlements for Gerente MDE (should see MDE settlements)
    const gerenteSettlements = await runWithContext(gerenteMde, async (tx) => {
      return tx.settlement.findMany({ where: { period: '2026-99' } });
    });
    assert(
      gerenteSettlements.length === 1 && gerenteSettlements[0].id === settlementMde.id,
      "Gerente MDE can see settlements in their hotel but not CTG's record"
    );

    // 6. Test RLS on Settlements for Admin (should see both)
    const adminSettlements = await runWithContext(adminUser, async (tx) => {
      return tx.settlement.findMany({ where: { period: '2026-99' } });
    });
    assert(
      adminSettlements.length === 2,
      "Admin can see all history records"
    );

    // 7. Verify audit_logs table write-only restriction
    const log = await runWithContext(adminUser, async (tx) => {
      return tx.auditLog.create({
        data: {
          userId: adminUser.id,
          action: 'CREATE',
          targetTable: 'compensation_plans',
          targetId: 9999,
          ipAddress: '127.0.0.1'
        }
      });
    });

    let updateFailed = false;
    try {
      await runWithContext(adminUser, async (tx) => {
        await tx.auditLog.update({
          where: { id: log.id },
          data: { ipAddress: '192.168.1.1' }
        });
      });
    } catch (e) {
      updateFailed = true;
    }
    assert(updateFailed, "AuditLog update is blocked by RLS even for admin");

    let deleteFailed = false;
    try {
      await runWithContext(adminUser, async (tx) => {
        await tx.auditLog.delete({
          where: { id: log.id }
        });
      });
    } catch (e) {
      deleteFailed = true;
    }
    assert(deleteFailed, "AuditLog delete is blocked by RLS even for admin");

  } catch (err) {
    console.error("Error in Phase 6 RLS integration tests:", err);
    failed++;
  } finally {
    // 8. Cleanup
    console.log("\nCleaning up test settlements...");
    try {
      await runWithContext(adminUser, async (tx) => {
        await tx.settlement.deleteMany({
          where: { id: { in: [settlementMde?.id, settlementCtg?.id].filter(Boolean) } }
        });
      });
    } catch (err) {
      console.error("Cleanup failed", err);
    }
  }

  console.log(`\n=== PHASE 6 TEST RESULTS: ${passed} PASSED, ${failed} FAILED ===`);
  if (failed > 0) {
    process.exit(1);
  } else {
    process.exit(0);
  }
}

runTests().catch(err => {
  console.error("Fatal test runner error:", err);
  process.exit(1);
});
