// CSRF Detector - Detects Cross-Site Request Forgery attempts
// Browser Techniques Line 86: Auto-submit on load
// Script auto-submits a form when the page loads

import { BaseDetector } from '../base-detector.js';

export class CsrfDetector extends BaseDetector {
  constructor(config = {}) {
    super({
      name: 'csrf-detector',
      category: 'cross-site',
      version: '1.0.0',
      description: 'Detects CSRF attempts via auto-submit forms and GET-based state changes',
      weight: 2,
      severity: 'medium',
      ...config
    });
  }

  async detect(target, ruleRegistry) {
    const findings = [];

    // This detector requires DOM data from content script
    const forms = target.forms || [];
    const iframes = target.iframes || [];
    const requests = target.requests || [];

    if (forms.length === 0 && iframes.length === 0 && requests.length === 0) {
      return this.createResult(false, [], 0);
    }

    const rules = ruleRegistry.getRules('cross-site', 'csrf');

    if (!rules) {
      return this.createResult(false, [], 0);
    }

    const currentOrigin = target.currentOrigin || window.location.origin;

    // 1. Detect auto-submitting forms
    for (const form of forms) {
      if (form.hasAutoSubmit || form.submitsOnLoad) {
        const isCrossOrigin = this.isCrossOrigin(form.action, currentOrigin);

        findings.push(this.createFinding({
          pattern: 'auto-submit-form',
          matched: form.action,
          description: 'Form auto-submits on page load (potential CSRF)',
          severity: isCrossOrigin ? 'high' : 'medium',
          weight: isCrossOrigin ? 4 : 2,
          metadata: {
            formAction: form.action,
            method: form.method,
            isCrossOrigin,
            technique: 'csrf-auto-submit'
          }
        }));
      }
    }

    // 2. Detect forms missing CSRF tokens
    for (const form of forms) {
      if (
        form.method === 'POST' &&
        !form.hasCsrfToken &&
        this.isStateChangingEndpoint(form.action, rules)
      ) {
        findings.push(this.createFinding({
          pattern: 'missing-csrf-token',
          matched: form.action,
          description: 'POST form to state-changing endpoint without CSRF token',
          severity: 'medium',
          weight: 2,
          metadata: {
            formAction: form.action,
            technique: 'csrf-vulnerability'
          }
        }));
      }
    }

    // 3. Detect hidden iframe form submissions
    for (const iframe of iframes) {
      if (iframe.hasForm && (iframe.isHidden || iframe.width < 10 || iframe.height < 10)) {
        findings.push(this.createFinding({
          pattern: 'hidden-iframe-form',
          matched: iframe.src || 'hidden iframe',
          description: 'Hidden iframe with form (potential CSRF via iframe)',
          severity: 'high',
          weight: 4,
          metadata: {
            iframeSrc: iframe.src,
            isHidden: iframe.isHidden,
            technique: 'iframe-csrf'
          }
        }));
      }
    }

    // 4. Detect GET requests to state-changing endpoints
    for (const request of requests) {
      if (
        request.method === 'GET' &&
        this.isStateChangingEndpoint(request.url, rules)
      ) {
        findings.push(this.createFinding({
          pattern: 'get-state-change',
          matched: request.url,
          description: 'GET request to state-changing endpoint (CSRF vulnerability)',
          severity: 'high',
          weight: 3,
          metadata: {
            url: request.url,
            technique: 'get-based-csrf'
          }
        }));
      }
    }

    // 5. Detect suspicious cross-origin form targets
    for (const form of forms) {
      const isCrossOrigin = this.isCrossOrigin(form.action, currentOrigin);

      if (isCrossOrigin && form.method === 'POST') {
        const destinationDomain = new URL(form.action).hostname;

        // Check if destination is suspicious
        if (this.isSuspiciousDomain(destinationDomain, rules)) {
          findings.push(this.createFinding({
            pattern: 'suspicious-csrf-target',
            matched: form.action,
            description: 'Form submits to suspicious cross-origin endpoint',
            severity: 'critical',
            weight: 5,
            metadata: {
              formAction: form.action,
              destinationDomain,
              technique: 'malicious-csrf'
            }
          }));
        }
      }
    }

    // 6. Detect rapid form submissions (CSRF attack in progress)
    if (target.formSubmissionCount > (rules.rapidSubmissionThreshold || 3)) {
      findings.push(this.createFinding({
        pattern: 'rapid-form-submissions',
        matched: `${target.formSubmissionCount} submissions`,
        description: 'Multiple rapid form submissions detected',
        severity: 'high',
        weight: 4,
        metadata: {
          count: target.formSubmissionCount,
          technique: 'csrf-flooding'
        }
      }));
    }

    // 7. Detect forms with only hidden inputs (classic CSRF pattern)
    for (const form of forms) {
      if (form.inputCount > 0 && form.visibleInputCount === 0) {
        findings.push(this.createFinding({
          pattern: 'all-hidden-inputs',
          matched: `${form.inputCount} hidden inputs`,
          description: 'Form contains only hidden inputs (CSRF pattern)',
          severity: 'medium',
          weight: 2,
          metadata: {
            formAction: form.action,
            inputCount: form.inputCount,
            technique: 'hidden-csrf-form'
          }
        }));
      }
    }

    const matched = findings.length > 0;
    const riskScore = findings.reduce((sum, f) => sum + (f.weight || 1), 0);

    return this.createResult(matched, findings, riskScore);
  }

  isCrossOrigin(actionUrl, currentOrigin) {
    try {
      const actionOrigin = new URL(actionUrl, currentOrigin).origin;
      return actionOrigin !== currentOrigin;
    } catch {
      return false;
    }
  }

  isStateChangingEndpoint(url, rules) {
    const stateChangingPatterns = rules.stateChangingPatterns || [
      '/transfer',
      '/send',
      '/delete',
      '/remove',
      '/update',
      '/create',
      '/add',
      '/post',
      '/submit',
      '/change',
      '/modify',
      '/edit',
      '/purchase',
      '/buy',
      '/checkout',
      '/payment'
    ];

    const urlLower = url.toLowerCase();
    return stateChangingPatterns.some(pattern => urlLower.includes(pattern));
  }

  isSuspiciousDomain(domain, rules) {
    const suspiciousTLDs = rules.suspiciousTLDs || [
      '.tk',
      '.ml',
      '.ga',
      '.cf',
      '.gq'
    ];

    return suspiciousTLDs.some(tld => domain.endsWith(tld));
  }
}
