/**
 * AI Security Analyzer Service
 *
 * Uses Claude Opus 4.5 to perform intelligent security analysis of the codebase.
 * Scans for vulnerabilities, misconfigurations, and potential attack vectors.
 *
 * @module services/ai-security-analyzer
 */

import Anthropic from '@anthropic-ai/sdk';
import { logger } from '@/lib/logger';
import { createId } from '@paralleldrive/cuid2';
import * as fs from 'fs';
import * as path from 'path';

/**
 * AI Analysis Result
 */
export interface AISecurityFinding {
  id: string;
  severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
  category: string;
  title: string;
  description: string;
  file?: string;
  line?: number;
  code?: string;
  remediation: string;
  cweId?: string;
  confidence: 'high' | 'medium' | 'low';
}

/**
 * AI Security Analysis Result
 */
export interface AISecurityAnalysis {
  analysisId: string;
  timestamp: Date;
  duration: number;
  findings: AISecurityFinding[];
  summary: {
    totalFindings: number;
    critical: number;
    high: number;
    medium: number;
    low: number;
    info: number;
    overallRisk: 'critical' | 'high' | 'medium' | 'low' | 'minimal';
    aiConfidence: number;
  };
  areasAnalyzed: string[];
  recommendations: string[];
}

/**
 * Files and patterns to analyze
 */
const SECURITY_SCAN_TARGETS = {
  // Authentication & Authorization
  auth: [
    'lib/auth.ts',
    'lib/staff-session.ts',
    'middleware.ts',
    'app/api/auth/**/*.ts',
  ],
  // API Routes
  api: [
    'app/api/**/route.ts',
  ],
  // Database & Data handling
  database: [
    'lib/db.ts',
    'lib/supabase.ts',
    'lib/dual-database.ts',
    'prisma/schema.prisma',
  ],
  // Security utilities
  security: [
    'lib/csrf.ts',
    'lib/rate-limit*.ts',
    'lib/api-security.ts',
    'lib/secure-tokens.ts',
  ],
  // Configuration
  config: [
    '.env.example',
    'next.config.mjs',
    'vercel.json',
  ],
  // Sensitive services
  services: [
    'lib/services/otp.service.ts',
    'lib/services/subscription-access.service.ts',
    'lib/stripe.ts',
    'lib/webhooks.ts',
  ],
};

/**
 * Security analysis prompts for Claude
 */
const SECURITY_ANALYSIS_PROMPTS = {
  codeReview: `You are a senior security engineer performing a comprehensive security audit. Analyze the following code for security vulnerabilities.

Focus on:
1. Authentication/Authorization flaws (broken auth, privilege escalation)
2. Injection vulnerabilities (SQL, NoSQL, Command, XSS)
3. Sensitive data exposure (hardcoded secrets, PII leaks)
4. Security misconfigurations
5. Broken access control
6. Cryptographic failures
7. SSRF vulnerabilities
8. Insecure deserialization
9. Rate limiting gaps
10. CSRF vulnerabilities

For each finding, provide:
- Severity (critical/high/medium/low/info)
- Category (e.g., "Authentication", "Injection", "Data Exposure")
- Clear title
- Detailed description of the vulnerability
- The specific file and line number if applicable
- Remediation steps
- CWE ID if applicable
- Confidence level (high/medium/low)

Return your findings as a JSON array. If no vulnerabilities found, return an empty array.`,

  configReview: `You are a security engineer reviewing configuration files for security issues.

Analyze for:
1. Exposed secrets or credentials
2. Insecure default settings
3. Missing security headers
4. Overly permissive CORS settings
5. Debug mode enabled in production
6. Missing rate limiting
7. Insecure cookie settings
8. Missing CSP headers
9. Exposed internal endpoints
10. Misconfigured authentication

Return findings as JSON array with severity, category, title, description, and remediation.`,

  apiSecurity: `You are an API security specialist. Review this API endpoint code for vulnerabilities.

Check for:
1. Missing authentication
2. Missing authorization checks
3. Input validation gaps
4. SQL/NoSQL injection
5. Mass assignment vulnerabilities
6. Rate limiting absence
7. Sensitive data in responses
8. IDOR vulnerabilities
9. Broken function level authorization
10. Improper error handling that leaks info

Return findings as JSON array.`,
};

/**
 * AI Security Analyzer Service
 */
export class AISecurityAnalyzerService {
  private client: Anthropic | null = null;
  private projectRoot: string;

  constructor() {
    this.projectRoot = process.cwd();

    // Initialize Anthropic client if API key is available
    const apiKey = process.env.ANTHROPIC_API_KEY;
    if (apiKey) {
      this.client = new Anthropic({ apiKey });
      logger.info('AI Security Analyzer initialized with Claude Opus 4.5');
    } else {
      logger.warn('ANTHROPIC_API_KEY not set - AI security analysis disabled');
    }
  }

  /**
   * Run a full AI-powered security analysis
   */
  async runFullAnalysis(): Promise<AISecurityAnalysis> {
    const analysisId = createId();
    const startTime = Date.now();
    const findings: AISecurityFinding[] = [];
    const areasAnalyzed: string[] = [];

    logger.info('Starting AI security analysis', { analysisId });

    if (!this.client) {
      logger.error('Anthropic client not initialized');
      return this.createEmptyAnalysis(analysisId, startTime, 'API key not configured');
    }

    try {
      // Analyze authentication code
      const authFindings = await this.analyzeCategory('auth', SECURITY_ANALYSIS_PROMPTS.codeReview);
      findings.push(...authFindings);
      areasAnalyzed.push('Authentication & Authorization');

      // Analyze API routes (sample)
      const apiFindings = await this.analyzeApiRoutes();
      findings.push(...apiFindings);
      areasAnalyzed.push('API Endpoints');

      // Analyze database code
      const dbFindings = await this.analyzeCategory('database', SECURITY_ANALYSIS_PROMPTS.codeReview);
      findings.push(...dbFindings);
      areasAnalyzed.push('Database Layer');

      // Analyze security utilities
      const securityFindings = await this.analyzeCategory('security', SECURITY_ANALYSIS_PROMPTS.codeReview);
      findings.push(...securityFindings);
      areasAnalyzed.push('Security Utilities');

      // Analyze configuration
      const configFindings = await this.analyzeCategory('config', SECURITY_ANALYSIS_PROMPTS.configReview);
      findings.push(...configFindings);
      areasAnalyzed.push('Configuration Files');

      // Analyze sensitive services
      const serviceFindings = await this.analyzeCategory('services', SECURITY_ANALYSIS_PROMPTS.codeReview);
      findings.push(...serviceFindings);
      areasAnalyzed.push('Sensitive Services');

      // Generate overall recommendations
      const recommendations = await this.generateRecommendations(findings);

      const duration = Date.now() - startTime;
      const summary = this.calculateSummary(findings);

      logger.info('AI security analysis completed', {
        analysisId,
        duration,
        totalFindings: findings.length,
        overallRisk: summary.overallRisk,
      });

      return {
        analysisId,
        timestamp: new Date(),
        duration,
        findings,
        summary,
        areasAnalyzed,
        recommendations,
      };
    } catch (error) {
      logger.error('AI security analysis failed', {
        analysisId,
        error: error instanceof Error ? error.message : String(error),
      });
      return this.createEmptyAnalysis(analysisId, startTime, String(error));
    }
  }

  /**
   * Analyze a specific category of files
   */
  private async analyzeCategory(
    category: keyof typeof SECURITY_SCAN_TARGETS,
    prompt: string
  ): Promise<AISecurityFinding[]> {
    const patterns = SECURITY_SCAN_TARGETS[category];
    const findings: AISecurityFinding[] = [];

    for (const pattern of patterns) {
      const files = await this.resolveFilePattern(pattern);

      for (const file of files.slice(0, 5)) { // Limit to 5 files per pattern
        try {
          const content = await this.readFileContent(file);
          if (!content) continue;

          const fileFindings = await this.analyzeCodeWithClaude(file, content, prompt);
          findings.push(...fileFindings);
        } catch (error) {
          logger.warn('Failed to analyze file', { file, error: String(error) });
        }
      }
    }

    return findings;
  }

  /**
   * Analyze API routes
   */
  private async analyzeApiRoutes(): Promise<AISecurityFinding[]> {
    const findings: AISecurityFinding[] = [];

    // Find critical API routes
    const criticalRoutes = [
      'app/api/auth/login/route.ts',
      'app/api/auth/verify-otp/route.ts',
      'app/api/stripe/webhook/route.ts',
      'app/api/user/profile/route.ts',
      'app/api/subscriptions/create-checkout/route.ts',
    ];

    for (const route of criticalRoutes) {
      try {
        const fullPath = path.join(this.projectRoot, route);
        const content = await this.readFileContent(fullPath);
        if (!content) continue;

        const routeFindings = await this.analyzeCodeWithClaude(
          route,
          content,
          SECURITY_ANALYSIS_PROMPTS.apiSecurity
        );
        findings.push(...routeFindings);
      } catch {
        // File might not exist
      }
    }

    return findings;
  }

  /**
   * Analyze code using Claude Opus 4.5
   */
  private async analyzeCodeWithClaude(
    filename: string,
    code: string,
    systemPrompt: string
  ): Promise<AISecurityFinding[]> {
    if (!this.client) return [];

    try {
      const response = await this.client.messages.create({
        model: 'claude-sonnet-4-20250514', // Using Claude Sonnet 4 for efficiency, can upgrade to Opus
        max_tokens: 4096,
        system: systemPrompt,
        messages: [
          {
            role: 'user',
            content: `Analyze this file for security vulnerabilities:\n\nFile: ${filename}\n\n\`\`\`\n${code.slice(0, 15000)}\n\`\`\`\n\nReturn your findings as a JSON array. Example format:\n[{"severity": "high", "category": "Authentication", "title": "Missing auth check", "description": "...", "file": "${filename}", "line": 42, "remediation": "...", "confidence": "high"}]`,
          },
        ],
      });

      // Extract JSON from response
      const content = response.content[0];
      if (content.type !== 'text') return [];

      const jsonMatch = content.text.match(/\[[\s\S]*\]/);
      if (!jsonMatch) return [];

      const parsed = JSON.parse(jsonMatch[0]);
      return parsed.map((f: Partial<AISecurityFinding>) => ({
        id: createId(),
        severity: f.severity || 'info',
        category: f.category || 'General',
        title: f.title || 'Untitled finding',
        description: f.description || '',
        file: f.file || filename,
        line: f.line,
        code: f.code,
        remediation: f.remediation || 'Review and fix the identified issue',
        cweId: f.cweId,
        confidence: f.confidence || 'medium',
      }));
    } catch (error) {
      logger.warn('Claude analysis failed for file', {
        filename,
        error: error instanceof Error ? error.message : String(error),
      });
      return [];
    }
  }

  /**
   * Generate overall security recommendations
   */
  private async generateRecommendations(findings: AISecurityFinding[]): Promise<string[]> {
    if (!this.client || findings.length === 0) {
      return [
        'Continue regular security scans',
        'Keep dependencies updated',
        'Review access controls periodically',
      ];
    }

    try {
      const findingSummary = findings
        .slice(0, 20)
        .map((f) => `- [${f.severity.toUpperCase()}] ${f.title}: ${f.description}`)
        .join('\n');

      const response = await this.client.messages.create({
        model: 'claude-sonnet-4-20250514',
        max_tokens: 1024,
        messages: [
          {
            role: 'user',
            content: `Based on these security findings, provide 5-7 prioritized recommendations:\n\n${findingSummary}\n\nReturn as a JSON array of strings.`,
          },
        ],
      });

      const content = response.content[0];
      if (content.type !== 'text') return [];

      const jsonMatch = content.text.match(/\[[\s\S]*\]/);
      if (!jsonMatch) return [];

      return JSON.parse(jsonMatch[0]);
    } catch {
      return [
        'Address critical and high severity findings immediately',
        'Implement missing authentication checks',
        'Add input validation where needed',
        'Review and strengthen access controls',
      ];
    }
  }

  /**
   * Resolve file pattern to actual files
   */
  private async resolveFilePattern(pattern: string): Promise<string[]> {
    const files: string[] = [];

    if (pattern.includes('**')) {
      // For glob patterns, just return the base file if it exists
      const basePath = pattern.split('**')[0];
      const fullPath = path.join(this.projectRoot, basePath);
      if (fs.existsSync(fullPath)) {
        files.push(fullPath);
      }
    } else {
      const fullPath = path.join(this.projectRoot, pattern);
      if (fs.existsSync(fullPath)) {
        files.push(fullPath);
      }
    }

    return files;
  }

  /**
   * Read file content safely
   */
  private async readFileContent(filePath: string): Promise<string | null> {
    try {
      const absolutePath = path.isAbsolute(filePath)
        ? filePath
        : path.join(this.projectRoot, filePath);

      if (!fs.existsSync(absolutePath)) return null;

      const stat = fs.statSync(absolutePath);
      if (stat.size > 100000) {
        // Skip files larger than 100KB
        return null;
      }

      return fs.readFileSync(absolutePath, 'utf-8');
    } catch {
      return null;
    }
  }

  /**
   * Calculate analysis summary
   */
  private calculateSummary(findings: AISecurityFinding[]): AISecurityAnalysis['summary'] {
    const critical = findings.filter((f) => f.severity === 'critical').length;
    const high = findings.filter((f) => f.severity === 'high').length;
    const medium = findings.filter((f) => f.severity === 'medium').length;
    const low = findings.filter((f) => f.severity === 'low').length;
    const info = findings.filter((f) => f.severity === 'info').length;

    let overallRisk: AISecurityAnalysis['summary']['overallRisk'] = 'minimal';
    if (critical > 0) overallRisk = 'critical';
    else if (high > 0) overallRisk = 'high';
    else if (medium > 2) overallRisk = 'medium';
    else if (low > 5 || medium > 0) overallRisk = 'low';

    // Calculate AI confidence based on findings
    const highConfidence = findings.filter((f) => f.confidence === 'high').length;
    const aiConfidence = findings.length > 0
      ? Math.round((highConfidence / findings.length) * 100)
      : 100;

    return {
      totalFindings: findings.length,
      critical,
      high,
      medium,
      low,
      info,
      overallRisk,
      aiConfidence,
    };
  }

  /**
   * Create empty analysis result
   */
  private createEmptyAnalysis(
    analysisId: string,
    startTime: number,
    error: string
  ): AISecurityAnalysis {
    return {
      analysisId,
      timestamp: new Date(),
      duration: Date.now() - startTime,
      findings: [],
      summary: {
        totalFindings: 0,
        critical: 0,
        high: 0,
        medium: 0,
        low: 0,
        info: 0,
        overallRisk: 'minimal',
        aiConfidence: 0,
      },
      areasAnalyzed: [],
      recommendations: [`Analysis failed: ${error}`],
    };
  }

  /**
   * Quick scan specific file
   */
  async scanFile(filePath: string): Promise<AISecurityFinding[]> {
    const content = await this.readFileContent(filePath);
    if (!content) return [];

    return this.analyzeCodeWithClaude(filePath, content, SECURITY_ANALYSIS_PROMPTS.codeReview);
  }
}

// Export singleton
export const aiSecurityAnalyzerService = new AISecurityAnalyzerService();
