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

const PORT = 3016;
const BASE_URL = `http://localhost:${PORT}`;
const SCREENSHOT_DIR = path.join(__dirname, 'screenshots-phase6');

let nextProcess;
let prisma;
let pool;
let browser;

// Ensure screenshot dir exists
if (!fs.existsSync(SCREENSHOT_DIR)) {
  fs.mkdirSync(SCREENSHOT_DIR, { recursive: true });
}

function getPrisma() {
  if (!prisma) {
    const dbUrl = new URL(process.env.DATABASE_URL);
    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);
    prisma = new PrismaClient({ adapter });
  }
  return prisma;
}

async function runAsAdmin(queryFn) {
  const db = getPrisma();
  return db.$transaction(async (tx) => {
    await tx.$executeRawUnsafe(`SET LOCAL app.current_user_role = 'admin';`);
    return queryFn(tx);
  });
}

async function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

let passed = 0;
let failed = 0;

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

async function cleanupDb() {
  console.log("Cleaning up database records for Phase 6 tests...");
  await runAsAdmin(async (tx) => {
    // Delete settlements created during E2E tests
    await tx.settlement.deleteMany({
      where: { period: '2026-88' }
    });

    // Delete goals created during E2E tests
    await tx.goal.deleteMany({
      where: { period: '2026-88' }
    });

    // Delete sales results created during E2E tests
    await tx.salesResult.deleteMany({
      where: { period: '2026-88' }
    });
  });
}

async function main() {
  try {
    await cleanupDb();

    // 1. Fetch seeded users & plans
    console.log("Fetching seeded users...");
    const { adminUser, colaboradorMde, plan } = await runAsAdmin(async (tx) => {
      const users = await tx.user.findMany({ include: { hotel: true } });
      const adminUser = users.find(u => u.username === 'admin');
      const colaboradorMde = users.find(u => u.username === 'colaborador_mde');
      
      let p = await tx.compensationPlan.findFirst({ where: { status: 'ACTIVE' } });
      if (!p) {
        p = await tx.compensationPlan.create({
          data: {
            name: 'Test Active Plan',
            code: 'TEST-ACT-PLAN',
            validityStart: new Date(),
            type: 'PERCENTAGE',
            status: 'ACTIVE',
            createdBy: adminUser.id
          }
        });
      }
      return { adminUser, colaboradorMde, plan: p };
    });

    // 2. Seed settlement history data for 2026-88
    console.log("Seeding test settlement history...");
    await runAsAdmin(async (tx) => {
      await tx.goal.create({
        data: {
          targetType: 'INDIVIDUAL',
          targetId: colaboradorMde.id,
          period: '2026-88',
          amount: 10000.00
        }
      });

      await tx.salesResult.create({
        data: {
          source: 'EXCEL',
          hotelId: colaboradorMde.hotelId,
          userId: colaboradorMde.id,
          period: '2026-88',
          amount: 11000.00,
          salesCount: 8,
          idempotencyKey: 'test-key-p6-e2e-1',
          uploadedBy: adminUser.id,
          status: 'PROCESSED'
        }
      });

      await tx.settlement.create({
        data: {
          period: '2026-88',
          planId: plan.id,
          userId: colaboradorMde.id,
          salesAmount: 11000.00,
          goalAmount: 10000.00,
          achievementPercentage: 1.10,
          calculatedCommission: 1500.00,
          calculatedBonus: 0,
          adjustmentAmount: 0,
          totalPayout: 1500.00,
          status: 'APPROVED',
          aiAudited: true,
          aiAuditNotes: {
            es: 'Nota de auditoría en Español: Todo correcto.',
            en: 'Audit note in English: All correct.'
          }
        }
      });
    });

    // 3. Start Next.js production server on port 3016
    console.log(`Starting Next.js production server on port ${PORT}...`);
    nextProcess = spawn('node', ['node_modules/next/dist/bin/next', 'start', '--port', String(PORT)], {
      env: { ...process.env, PORT: String(PORT), IS_E2E_TEST: 'true' }
    });

    nextProcess.stdout.on('data', (data) => {
      console.log(`[Next.js] ${data.toString().trim()}`);
    });
    nextProcess.stderr.on('data', (data) => {
      console.error(`[Next.js ERR] ${data.toString().trim()}`);
    });

    // Wait for server to start up
    let serverReady = false;
    for (let i = 0; i < 15; i++) {
      await sleep(2000);
      try {
        await fetch(`${BASE_URL}/api/auth/me`);
        serverReady = true;
        break;
      } catch (e) {
        // Server not ready yet
      }
    }

    if (!serverReady) {
      console.error("Error: Next.js server failed to start within timeout.");
      await cleanup();
      process.exit(1);
    }
    console.log("Next.js server is ready!");

    // 4. Launch Puppeteer browser
    console.log("Launching Puppeteer browser...");
    browser = await puppeteer.launch({
      headless: 'shell',
      args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu']
    });

    const page = await browser.newPage();
    await page.setViewport({ width: 1280, height: 800 });

    // --- TEST 1: COLABORADOR HISTORY ---
    console.log("\n[Test 1] Logging in as Collaborator and checking history dashboard...");
    await page.goto(`${BASE_URL}/login`);
    await page.type('#username', 'colaborador_mde');
    await page.type('#password', 'password123');
    await page.click('button[type="submit"]');
    await page.waitForNavigation({ waitUntil: 'networkidle0' });

    // Verify redirected to /plans or check page header
    await page.goto(`${BASE_URL}/history`);
    await page.waitForSelector('[data-settlement-id]');
    
    await page.screenshot({ path: path.join(SCREENSHOT_DIR, '01_history_loaded.png') });
    console.log("Screenshot saved: 01_history_loaded.png");

    // Verify details
    const textContent = await page.evaluate(() => document.body.innerText);
    assert(textContent.includes('2026-88'), "History page displays the correct settlement period.");
    assert(textContent.includes(plan.code), "History page displays the plan code.");

    // Toggle notes
    console.log("Toggling AI audit notes...");
    await page.click('[id^="btn-toggle-notes-"]');
    await sleep(1000);
    
    await page.screenshot({ path: path.join(SCREENSHOT_DIR, '02_history_notes_expanded.png') });
    console.log("Screenshot saved: 02_history_notes_expanded.png");

    const notesText = await page.evaluate(() => document.body.innerText);
    assert(
      notesText.includes('Nota de auditoría en Español: Todo correcto.'),
      "AI Audit Notes display in Spanish (default locale)"
    );

    // Trigger language switch
    console.log("Switching language to English...");
    await page.select('#language-selector', 'en');
    await sleep(1000);

    await page.screenshot({ path: path.join(SCREENSHOT_DIR, '03_history_english.png') });
    console.log("Screenshot saved: 03_history_english.png");

    const englishText = await page.evaluate(() => document.body.innerText);
    assert(
      englishText.includes('Audit note in English: All correct.'),
      "AI Audit Notes successfully localized to English after switcher trigger"
    );

    // Logout
    console.log("Logging out...");
    await page.click('button:last-of-type'); // Logout button
    await page.waitForNavigation({ waitUntil: 'networkidle0' });

    // --- TEST 2: EXECUTIVE DASHBOARD ---
    console.log("\n[Test 2] Logging in as Admin and checking Executive Dashboard...");
    await page.goto(`${BASE_URL}/login`);
    await page.type('#username', 'admin');
    await page.type('#password', 'password123');
    await page.click('button[type="submit"]');
    await page.waitForNavigation({ waitUntil: 'networkidle0' });

    await page.goto(`${BASE_URL}/dashboard`);
    await page.waitForSelector('#dashboard-main-view');
    
    await page.screenshot({ path: path.join(SCREENSHOT_DIR, '04_dashboard_loaded.png') });
    console.log("Screenshot saved: 04_dashboard_loaded.png");

    const dashContent = await page.evaluate(() => document.body.innerText);
    assert(dashContent.includes('Tablero de Análisis de Compensación') || dashContent.includes('Compensation Analytics Dashboard'), "Dashboard page title loaded successfully.");
    
    // Check if charts are mounted (recharts responsiveness renders SVG)
    const chartSvgExists = await page.evaluate(() => {
      return document.querySelector('.recharts-responsive-container') !== null;
    });
    assert(chartSvgExists, "Executive dashboard renders Recharts visualizations.");

    // --- TEST 3: SYSTEM AUDIT LOGS ---
    console.log("\n[Test 3] Navigating to System Audit Logs...");
    await page.goto(`${BASE_URL}/admin/audit-logs`);
    await page.waitForSelector('#audit-logs-main-view');
    await page.waitForSelector('[data-audit-id]');

    await page.screenshot({ path: path.join(SCREENSHOT_DIR, '05_audit_logs_loaded.png') });
    console.log("Screenshot saved: 05_audit_logs_loaded.png");

    const auditContent = await page.evaluate(() => document.body.innerText);
    assert(auditContent.includes('Registros de Auditoría del Sistema') || auditContent.includes('System Audit Logs'), "Audit Logs title loaded successfully.");

    // Click a row to see JSON diff
    console.log("Clicking audit log row...");
    await page.click('[data-audit-id]');
    await sleep(1000);

    await page.screenshot({ path: path.join(SCREENSHOT_DIR, '06_audit_logs_diff.png') });
    console.log("Screenshot saved: 06_audit_logs_diff.png");

    const diffPanelText = await page.evaluate(() => document.body.innerText);
    console.log("DEBUG: diffPanelText is:", diffPanelText);
    const lowerText = diffPanelText.toLowerCase();
    assert(lowerText.includes('anterior') || lowerText.includes('previous') || lowerText.includes('nuevo') || lowerText.includes('new'), "Selecting log entry displays side-by-side JSON diff details panel.");

    console.log(`\n=== UI E2E TEST RUN COMPLETE: ${passed} PASSED, ${failed} FAILED ===`);

  } catch (err) {
    console.error("UI Test script failed:", err);
    failed++;
  } finally {
    await cleanup();
    if (failed > 0) {
      process.exit(1);
    } else {
      process.exit(0);
    }
  }
}

// Helper to look up compiled class names or selectors in module.css (or hardcode/approximate them since they start with page_*)
function stylesClass(className) {
  // Since CSS module classes are hashed, we can use selectors containing the class name
  return className;
}

async function cleanup() {
  console.log("Cleaning up resources...");
  try {
    await cleanupDb();
  } catch (err) {
    console.error("Error during cleanupDb:", err);
  }
  if (browser) {
    await browser.close();
  }
  if (nextProcess) {
    nextProcess.kill('SIGINT');
  }
  if (pool) {
    await pool.end();
  }
}

main();
