const { chromium } = require('playwright');
const fs = require('fs').promises;
const path = require('path');

/**
 * Comprehensive QA and Access Control Audit
 * Tests all protected routes with different user roles using specified MCP tools
 */

// Test configuration - using network address for proper deployment testing
const BASE_URL = 'http://192.168.0.46:3000';
const SCREENSHOT_DIR = './screenshots';
const AUDIT_RESULTS = [];

// Test users as specified in audit requirements
const TEST_USERS = {
  admin: { email: 'admin@bct.com', password: 'password123', role: 'admin' },
  user: { email: 'user@bct.com', password: 'password123', role: 'user' },
  backup_admin: { email: 'tmartinez@gmail.com', password: 'Skittles@420', role: 'admin' }
};

// Protected routes to test
const PROTECTED_ROUTES = [
  '/dashboard',
  '/events/new',
  '/events/1/manage', // Using a test event ID
  '/calendar',
  '/templates',
  '/scan'
];

/**
 * Initialize audit environment
 */
async function initializeAudit() {
  console.log('🎯 Starting Comprehensive QA Audit');
  console.log('📅 Date:', new Date().toISOString());
  console.log('🐳 Docker Environment: localhost:3000');
  
  // Create screenshots directory
  try {
    await fs.mkdir(SCREENSHOT_DIR, { recursive: true });
    console.log('📸 Screenshots directory created');
  } catch (error) {
    console.log('📸 Screenshots directory already exists');
  }
}

/**
 * Take screenshot and save using mcp__fs__save_file pattern
 */
async function takeScreenshot(page, filename, description) {
  const screenshotPath = path.join(SCREENSHOT_DIR, `${filename}.png`);
  await page.screenshot({ path: screenshotPath, fullPage: true });
  console.log(`📸 Screenshot saved: ${filename}.png - ${description}`);
  return screenshotPath;
}

/**
 * Test authentication with different user types
 */
async function testAuthentication(page, user) {
  console.log(`🔐 Testing authentication for ${user.role}: ${user.email}`);
  
  try {
    // Navigate to login page
    await page.goto(`${BASE_URL}/login-new`);
    await page.waitForLoadState('networkidle');
    
    // Take screenshot of login page
    await takeScreenshot(page, `login_page_${user.role}`, `Login page for ${user.role}`);
    
    // Fill login form
    await page.fill('input[type="email"]', user.email);
    await page.fill('input[type="password"]', user.password);
    
    // Take screenshot of filled form
    await takeScreenshot(page, `login_form_filled_${user.role}`, `Login form filled for ${user.role}`);
    
    // Submit form
    await page.click('button[type="submit"]');
    await page.waitForLoadState('networkidle');
    
    // Check if login was successful
    const currentUrl = page.url();
    const isLoggedIn = !currentUrl.includes('/login');
    
    // Take screenshot of result
    await takeScreenshot(page, `login_result_${user.role}`, `Login result for ${user.role}`);
    
    return {
      success: isLoggedIn,
      redirectUrl: currentUrl,
      screenshot: `login_result_${user.role}.png`
    };
    
  } catch (error) {
    console.error(`❌ Authentication failed for ${user.role}:`, error.message);
    await takeScreenshot(page, `login_error_${user.role}`, `Login error for ${user.role}`);
    return {
      success: false,
      error: error.message,
      screenshot: `login_error_${user.role}.png`
    };
  }
}

/**
 * Test route access for specific user role
 */
async function testRouteAccess(page, route, userRole, isAuthenticated) {
  console.log(`🧭 Testing route ${route} for ${userRole} (auth: ${isAuthenticated})`);
  
  const testResult = {
    route,
    role: userRole,
    auth: isAuthenticated ? '✅ logged in' : '❌ not logged in',
    access: '',
    errors: [],
    screenshot: '',
    notes: ''
  };
  
  try {
    // Navigate to route
    await page.goto(`${BASE_URL}${route}`);
    await page.waitForLoadState('networkidle', { timeout: 10000 });
    
    const currentUrl = page.url();
    const title = await page.title();
    
    // Check for redirects
    if (currentUrl !== `${BASE_URL}${route}`) {
      if (currentUrl.includes('/login')) {
        testResult.access = isAuthenticated ? '❌ blocked - should be allowed' : '✅ properly redirected to login';
        testResult.notes = `Redirected to login page`;
      } else {
        testResult.access = '⚠️ unexpected redirect';
        testResult.notes = `Redirected to: ${currentUrl}`;
      }
    } else {
      testResult.access = isAuthenticated ? '✅ allowed' : '❌ not protected - security issue';
    }
    
    // Check for errors in console
    const logs = [];
    page.on('console', msg => {
      if (msg.type() === 'error') {
        logs.push(msg.text());
      }
    });
    
    // Check for error messages on page
    const errorElements = await page.$$('[class*="error"], .alert-error, .error-message');
    for (const element of errorElements) {
      const errorText = await element.textContent();
      if (errorText && errorText.trim()) {
        testResult.errors.push(errorText.trim());
      }
    }
    
    // Take screenshot
    const screenshotName = `${route.replace(/\//g, '_')}_${userRole}_${isAuthenticated ? 'auth' : 'guest'}`;
    testResult.screenshot = await takeScreenshot(page, screenshotName, `Route ${route} for ${userRole}`);
    
    // Test UI elements based on role
    if (isAuthenticated && testResult.access.includes('✅')) {
      await testUIElements(page, route, userRole, testResult);
    }
    
  } catch (error) {
    testResult.access = '❌ error loading page';
    testResult.errors.push(error.message);
    testResult.notes = `Page load error: ${error.message}`;
    
    const screenshotName = `${route.replace(/\//g, '_')}_${userRole}_error`;
    testResult.screenshot = await takeScreenshot(page, screenshotName, `Error on ${route} for ${userRole}`);
  }
  
  return testResult;
}

/**
 * Test UI elements and functionality
 */
async function testUIElements(page, route, userRole, testResult) {
  try {
    // Check for navigation elements
    const navElements = await page.$$('nav, .navigation, [class*="nav"]');
    if (navElements.length === 0) {
      testResult.notes += ' | No navigation found';
    }
    
    // Check for user menu/profile
    const userMenu = await page.$('[class*="user"], [class*="profile"], .user-menu');
    if (!userMenu && userRole !== 'guest') {
      testResult.notes += ' | No user menu found';
    }
    
    // Check for admin-specific elements
    if (userRole === 'admin') {
      const adminElements = await page.$$('[class*="admin"], .admin-only, [data-role="admin"]');
      if (adminElements.length === 0 && route.includes('admin')) {
        testResult.notes += ' | No admin elements found on admin route';
      }
    }
    
    // Test form interactions if present
    const forms = await page.$$('form');
    if (forms.length > 0) {
      testResult.notes += ` | ${forms.length} forms found`;
      
      // Test first form if it exists
      const firstForm = forms[0];
      const submitButton = await firstForm.$('button[type="submit"], input[type="submit"]');
      if (submitButton) {
        const isDisabled = await submitButton.isDisabled();
        if (isDisabled) {
          testResult.notes += ' | Submit button disabled';
        }
      }
    }
    
  } catch (error) {
    testResult.notes += ` | UI test error: ${error.message}`;
  }
}

/**
 * Test guest (unauthenticated) access
 */
async function testGuestAccess(page) {
  console.log('👤 Testing guest (unauthenticated) access');
  
  const guestResults = [];
  
  for (const route of PROTECTED_ROUTES) {
    const result = await testRouteAccess(page, route, 'guest', false);
    guestResults.push(result);
    AUDIT_RESULTS.push(result);
  }
  
  return guestResults;
}

/**
 * Test authenticated user access
 */
async function testAuthenticatedAccess(page, user) {
  console.log(`👨‍💼 Testing authenticated access for ${user.role}: ${user.email}`);
  
  // First authenticate
  const authResult = await testAuthentication(page, user);
  
  if (!authResult.success) {
    console.log(`❌ Authentication failed for ${user.role}, skipping route tests`);
    return [];
  }
  
  console.log(`✅ Authentication successful for ${user.role}`);
  
  const routeResults = [];
  
  for (const route of PROTECTED_ROUTES) {
    const result = await testRouteAccess(page, route, user.role, true);
    routeResults.push(result);
    AUDIT_RESULTS.push(result);
  }
  
  return routeResults;
}

/**
 * Generate comprehensive audit report
 */
async function generateAuditReport() {
  const report = {
    auditDate: new Date().toISOString(),
    environment: 'Docker - localhost:3000',
    framework: 'Astro + Supabase Auth',
    totalTests: AUDIT_RESULTS.length,
    summary: {
      total: AUDIT_RESULTS.length,
      passed: AUDIT_RESULTS.filter(r => r.access.includes('✅')).length,
      failed: AUDIT_RESULTS.filter(r => r.access.includes('❌')).length,
      warnings: AUDIT_RESULTS.filter(r => r.access.includes('⚠️')).length
    },
    results: AUDIT_RESULTS
  };
  
  // Save JSON report
  const reportPath = './comprehensive-qa-audit-report.json';
  await fs.writeFile(reportPath, JSON.stringify(report, null, 2));
  console.log(`📊 Audit report saved: ${reportPath}`);
  
  // Save markdown report
  const markdownReport = generateMarkdownReport(report);
  const markdownPath = './COMPREHENSIVE_QA_AUDIT_REPORT.md';
  await fs.writeFile(markdownPath, markdownReport);
  console.log(`📄 Markdown report saved: ${markdownPath}`);
  
  return report;
}

/**
 * Generate markdown report
 */
function generateMarkdownReport(report) {
  let markdown = `# Comprehensive QA Audit Report

**Date:** ${new Date(report.auditDate).toLocaleString()}  
**Environment:** ${report.environment}  
**Framework:** ${report.framework}  

## Executive Summary

- **Total Tests:** ${report.summary.total}
- **Passed:** ${report.summary.passed} ✅
- **Failed:** ${report.summary.failed} ❌  
- **Warnings:** ${report.summary.warnings} ⚠️

## Detailed Results

`;

  // Group results by route
  const routeGroups = {};
  report.results.forEach(result => {
    if (!routeGroups[result.route]) {
      routeGroups[result.route] = [];
    }
    routeGroups[result.route].push(result);
  });

  Object.keys(routeGroups).forEach(route => {
    markdown += `### Route: ${route}\n\n`;
    
    routeGroups[route].forEach(result => {
      markdown += `#### ${result.role} access\n`;
      markdown += `- **Auth Status:** ${result.auth}\n`;
      markdown += `- **Access Result:** ${result.access}\n`;
      markdown += `- **Screenshot:** ${result.screenshot}\n`;
      
      if (result.errors.length > 0) {
        markdown += `- **Errors:** ${result.errors.join(', ')}\n`;
      }
      
      if (result.notes) {
        markdown += `- **Notes:** ${result.notes}\n`;
      }
      
      markdown += `\n`;
    });
    
    markdown += `---\n\n`;
  });

  return markdown;
}

/**
 * Main audit execution
 */
async function runComprehensiveAudit() {
  await initializeAudit();
  
  const browser = await chromium.launch({ 
    headless: false, // Set to true for production
    slowMo: 1000 // Slow down for demonstration
  });
  
  try {
    const page = await browser.newPage();
    
    // Configure page
    await page.setViewportSize({ width: 1920, height: 1080 });
    
    // 1. Test guest access first
    console.log('\n🚫 === TESTING GUEST ACCESS ===');
    await testGuestAccess(page);
    
    // 2. Test admin user access
    console.log('\n👨‍💼 === TESTING ADMIN ACCESS ===');
    
    // Try primary admin credentials first
    let adminResults = await testAuthenticatedAccess(page, TEST_USERS.admin);
    
    // If primary admin fails, try backup admin
    if (adminResults.length === 0) {
      console.log('🔄 Primary admin failed, trying backup admin credentials');
      await page.goto(`${BASE_URL}/login-new`); // Reset to login page
      adminResults = await testAuthenticatedAccess(page, TEST_USERS.backup_admin);
    }
    
    // 3. Test regular user access (skip if no user credentials work)
    console.log('\n👤 === TESTING USER ACCESS ===');
    await page.goto(`${BASE_URL}/login-new`); // Reset to login page
    await testAuthenticatedAccess(page, TEST_USERS.user);
    
    // 4. Generate comprehensive report
    console.log('\n📊 === GENERATING AUDIT REPORT ===');
    const finalReport = await generateAuditReport();
    
    console.log('\n✅ === AUDIT COMPLETED ===');
    console.log(`📊 Total tests: ${finalReport.summary.total}`);
    console.log(`✅ Passed: ${finalReport.summary.passed}`);
    console.log(`❌ Failed: ${finalReport.summary.failed}`);
    console.log(`⚠️ Warnings: ${finalReport.summary.warnings}`);
    
  } catch (error) {
    console.error('💥 Audit failed:', error);
    
    // Save error report
    const errorReport = {
      error: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString(),
      partialResults: AUDIT_RESULTS
    };
    
    await fs.writeFile('./audit-error-report.json', JSON.stringify(errorReport, null, 2));
    
  } finally {
    await browser.close();
  }
}

// Execute audit
if (require.main === module) {
  runComprehensiveAudit().catch(console.error);
}

module.exports = {
  runComprehensiveAudit,
  testAuthentication,
  testRouteAccess,
  generateAuditReport
};