/**
 * Security Analyzer Service for Redirect Intelligence v2
 * 
 * Analyzes security aspects of redirects and destinations
 */

import axios from 'axios';
import { URL } from 'url';
import { logger } from '../lib/logger';

export interface MixedContentAnalysis {
  status: 'none' | 'present' | 'final_to_http';
  insecureResources: string[];
  httpsToHttpRedirect: boolean;
}

export interface SecurityHeadersAnalysis {
  strictTransportSecurity?: string;
  contentSecurityPolicy?: string;
  xFrameOptions?: string;
  xContentTypeOptions?: string;
  referrerPolicy?: string;
  permissionsPolicy?: string;
  score: number; // 0-100 based on security headers
}

export interface SafeBrowsingResult {
  status: 'safe' | 'malware' | 'phishing' | 'unwanted_software' | 'unknown' | 'error';
  details?: string;
}

export interface SecurityFlags {
  safeBrowsingStatus: string;
  mixedContent: 'NONE' | 'PRESENT' | 'FINAL_TO_HTTP';
  httpsToHttp: boolean;
  securityHeaders: SecurityHeadersAnalysis;
  certificateValid?: boolean;
  weakCiphers: boolean;
  openRedirects: boolean;
}

export interface SecurityAnalysisResult {
  url: string;
  flags: SecurityFlags;
  mixedContentAnalysis: MixedContentAnalysis;
  safeBrowsing: SafeBrowsingResult;
  vulnerabilities: string[];
  recommendations: string[];
  securityScore: number; // 0-100
}

export class SecurityAnalyzerService {
  
  /**
   * Perform comprehensive security analysis
   */
  async analyzeSecurity(url: string, redirectChain?: string[]): Promise<SecurityAnalysisResult> {
    logger.info(`Starting security analysis for: ${url}`);
    
    const result: SecurityAnalysisResult = {
      url,
      flags: {
        safeBrowsingStatus: 'unknown',
        mixedContent: 'NONE',
        httpsToHttp: false,
        securityHeaders: { score: 0 },
        weakCiphers: false,
        openRedirects: false,
      },
      mixedContentAnalysis: {
        status: 'none',
        insecureResources: [],
        httpsToHttpRedirect: false,
      },
      safeBrowsing: { status: 'unknown' },
      vulnerabilities: [],
      recommendations: [],
      securityScore: 0,
    };
    
    try {
      // Analyze redirect chain for security issues
      if (redirectChain && redirectChain.length > 0) {
        this.analyzeRedirectChainSecurity(redirectChain, result);
      }
      
      // Analyze security headers
      const headersAnalysis = await this.analyzeSecurityHeaders(url);
      result.flags.securityHeaders = headersAnalysis;
      
      // Analyze mixed content
      const mixedContentAnalysis = await this.analyzeMixedContent(url);
      result.mixedContentAnalysis = mixedContentAnalysis;
      result.flags.mixedContent = mixedContentAnalysis.status === 'none' ? 'NONE' : 
                                 mixedContentAnalysis.status === 'final_to_http' ? 'FINAL_TO_HTTP' : 'PRESENT';
      result.flags.httpsToHttp = mixedContentAnalysis.httpsToHttpRedirect;
      
      // Safe browsing check (placeholder implementation)
      const safeBrowsingResult = await this.checkSafeBrowsing(url);
      result.safeBrowsing = safeBrowsingResult;
      result.flags.safeBrowsingStatus = safeBrowsingResult.status;
      
      // Generate security recommendations and score
      this.generateSecurityRecommendations(result);
      
      logger.info(`Security analysis completed for: ${url}`, {
        score: result.securityScore,
        safeBrowsing: result.safeBrowsing.status,
        mixedContent: result.flags.mixedContent,
        headersScore: result.flags.securityHeaders.score
      });
      
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown security analysis error';
      result.vulnerabilities.push(`Security analysis failed: ${errorMessage}`);
      logger.error(`Security analysis failed for ${url}:`, error);
    }
    
    return result;
  }
  
  /**
   * Analyze redirect chain for security issues
   */
  private analyzeRedirectChainSecurity(redirectChain: string[], result: SecurityAnalysisResult): void {
    for (let i = 0; i < redirectChain.length - 1; i++) {
      const currentUrl = redirectChain[i];
      const nextUrl = redirectChain[i + 1];
      
      try {
        const current = new URL(currentUrl);
        const next = new URL(nextUrl);
        
        // Check for HTTPS to HTTP downgrades
        if (current.protocol === 'https:' && next.protocol === 'http:') {
          result.flags.httpsToHttp = true;
          result.vulnerabilities.push(`Insecure redirect: HTTPS to HTTP (${currentUrl} → ${nextUrl})`);
        }
        
        // Check for suspicious redirects (different domains)
        if (current.hostname !== next.hostname) {
          // Basic open redirect detection
          if (this.isOpenRedirectVulnerable(currentUrl, nextUrl)) {
            result.flags.openRedirects = true;
            result.vulnerabilities.push(`Potential open redirect vulnerability: ${currentUrl} → ${nextUrl}`);
          }
        }
        
      } catch (error) {
        logger.warn(`Failed to parse URLs in redirect chain: ${currentUrl} → ${nextUrl}`);
      }
    }
  }
  
  /**
   * Check for potential open redirect vulnerabilities
   */
  private isOpenRedirectVulnerable(fromUrl: string, toUrl: string): boolean {
    try {
      const from = new URL(fromUrl);
      const to = new URL(toUrl);
      
      // Different domains might indicate open redirect
      if (from.hostname !== to.hostname) {
        // Check if the target URL is passed as a parameter
        const urlParams = new URLSearchParams(from.search);
        for (const [key, value] of urlParams.entries()) {
          if (key.toLowerCase().includes('url') || 
              key.toLowerCase().includes('redirect') ||
              key.toLowerCase().includes('return')) {
            if (value.includes(to.hostname)) {
              return true;
            }
          }
        }
      }
      
      return false;
    } catch {
      return false;
    }
  }
  
  /**
   * Analyze security headers
   */
  private async analyzeSecurityHeaders(url: string): Promise<SecurityHeadersAnalysis> {
    try {
      const response = await axios.head(url, {
        timeout: 5000,
        headers: {
          'User-Agent': 'RedirectIntelligence-Bot/2.0 (Security Analysis)',
        },
      });
      
      const headers = response.headers;
      let score = 0;
      
      const analysis: SecurityHeadersAnalysis = {
        score: 0,
      };
      
      // Strict-Transport-Security
      if (headers['strict-transport-security']) {
        analysis.strictTransportSecurity = headers['strict-transport-security'];
        score += 20;
      }
      
      // Content-Security-Policy
      if (headers['content-security-policy']) {
        analysis.contentSecurityPolicy = headers['content-security-policy'];
        score += 25;
      }
      
      // X-Frame-Options
      if (headers['x-frame-options']) {
        analysis.xFrameOptions = headers['x-frame-options'];
        score += 15;
      }
      
      // X-Content-Type-Options
      if (headers['x-content-type-options']) {
        analysis.xContentTypeOptions = headers['x-content-type-options'];
        score += 10;
      }
      
      // Referrer-Policy
      if (headers['referrer-policy']) {
        analysis.referrerPolicy = headers['referrer-policy'];
        score += 10;
      }
      
      // Permissions-Policy (formerly Feature-Policy)
      if (headers['permissions-policy'] || headers['feature-policy']) {
        analysis.permissionsPolicy = headers['permissions-policy'] || headers['feature-policy'];
        score += 10;
      }
      
      analysis.score = score;
      return analysis;
      
    } catch (error) {
      logger.warn(`Failed to analyze security headers for ${url}:`, error);
      return { score: 0 };
    }
  }
  
  /**
   * Analyze mixed content issues
   */
  private async analyzeMixedContent(url: string): Promise<MixedContentAnalysis> {
    const result: MixedContentAnalysis = {
      status: 'none',
      insecureResources: [],
      httpsToHttpRedirect: false,
    };
    
    try {
      const parsedUrl = new URL(url);
      
      // If the final URL is HTTP but we started with HTTPS, it's a security issue
      if (parsedUrl.protocol === 'http:') {
        result.status = 'final_to_http';
        result.httpsToHttpRedirect = true;
        return result;
      }
      
      // For HTTPS URLs, check for mixed content in the page
      if (parsedUrl.protocol === 'https:') {
        const mixedContentCheck = await this.checkPageMixedContent(url);
        if (mixedContentCheck.length > 0) {
          result.status = 'present';
          result.insecureResources = mixedContentCheck;
        }
      }
      
    } catch (error) {
      logger.warn(`Mixed content analysis failed for ${url}:`, error);
    }
    
    return result;
  }
  
  /**
   * Check page for mixed content issues
   */
  private async checkPageMixedContent(url: string): Promise<string[]> {
    try {
      const response = await axios.get(url, {
        timeout: 10000,
        headers: {
          'User-Agent': 'RedirectIntelligence-Bot/2.0 (Mixed Content Analysis)',
        },
        maxContentLength: 512 * 1024, // 512KB limit for mixed content analysis
      });
      
      const html = response.data;
      const insecureResources: string[] = [];
      
      // Look for HTTP resources in HTTPS pages
      const httpResourceRegex = /(?:src|href|action)=['"]http:\/\/[^'"]+['"]|url\(http:\/\/[^)]+\)/gi;
      let match;
      
      while ((match = httpResourceRegex.exec(html)) !== null) {
        const resource = match[0];
        const urlMatch = resource.match(/http:\/\/[^'")\s]+/);
        if (urlMatch) {
          insecureResources.push(urlMatch[0]);
        }
      }
      
      // Remove duplicates
      return [...new Set(insecureResources)];
      
    } catch (error) {
      logger.warn(`Failed to check mixed content for ${url}:`, error);
      return [];
    }
  }
  
  /**
   * Check URL against safe browsing (placeholder implementation)
   */
  private async checkSafeBrowsing(url: string): Promise<SafeBrowsingResult> {
    try {
      // This is a placeholder implementation
      // In production, you would integrate with Google Safe Browsing API
      // or similar service
      
      const parsedUrl = new URL(url);
      const hostname = parsedUrl.hostname.toLowerCase();
      
      // Basic checks for obviously suspicious patterns
      const suspiciousPatterns = [
        /phishing/i,
        /malware/i,
        /virus/i,
        /hack/i,
        /suspicious/i,
      ];
      
      for (const pattern of suspiciousPatterns) {
        if (pattern.test(hostname)) {
          return {
            status: 'phishing',
            details: 'Suspicious hostname pattern detected',
          };
        }
      }
      
      // Check for suspicious TLDs (basic implementation)
      const suspiciousTlds = ['.tk', '.ml', '.ga', '.cf'];
      const tld = hostname.substring(hostname.lastIndexOf('.'));
      
      if (suspiciousTlds.includes(tld)) {
        return {
          status: 'unwanted_software',
          details: 'Suspicious top-level domain',
        };
      }
      
      return { status: 'safe' };
      
    } catch (error) {
      logger.warn(`Safe browsing check failed for ${url}:`, error);
      return { 
        status: 'error',
        details: 'Safe browsing check failed',
      };
    }
  }
  
  /**
   * Generate security recommendations and calculate score
   */
  private generateSecurityRecommendations(result: SecurityAnalysisResult): void {
    let score = 100;
    
    // Safe browsing issues
    if (result.safeBrowsing.status === 'malware' || result.safeBrowsing.status === 'phishing') {
      result.vulnerabilities.push(`Site flagged as ${result.safeBrowsing.status}`);
      result.recommendations.push('Immediately investigate and resolve security issues');
      score -= 50;
    } else if (result.safeBrowsing.status === 'unwanted_software') {
      result.vulnerabilities.push('Site may contain unwanted software');
      result.recommendations.push('Review site content and remove unwanted software');
      score -= 30;
    }
    
    // Mixed content issues
    if (result.flags.httpsToHttp) {
      result.vulnerabilities.push('HTTPS to HTTP downgrade detected');
      result.recommendations.push('Ensure all redirects maintain HTTPS encryption');
      score -= 25;
    }
    
    if (result.mixedContentAnalysis.insecureResources.length > 0) {
      result.vulnerabilities.push(`${result.mixedContentAnalysis.insecureResources.length} insecure resources found`);
      result.recommendations.push('Update all HTTP resources to use HTTPS');
      score -= 15;
    }
    
    // Security headers
    const headersScore = result.flags.securityHeaders.score;
    if (headersScore < 50) {
      result.recommendations.push('Implement security headers (CSP, HSTS, X-Frame-Options)');
      score -= 20;
    } else if (headersScore < 80) {
      result.recommendations.push('Add additional security headers for better protection');
      score -= 10;
    }
    
    // Open redirects
    if (result.flags.openRedirects) {
      result.vulnerabilities.push('Potential open redirect vulnerability detected');
      result.recommendations.push('Validate and restrict redirect destinations');
      score -= 20;
    }
    
    // Adjust score based on headers
    score = Math.min(score, score + (headersScore * 0.2));
    
    result.securityScore = Math.max(0, score);
    
    // Add overall security assessment
    if (result.securityScore >= 90) {
      result.recommendations.push('Excellent security posture!');
    } else if (result.securityScore >= 70) {
      result.recommendations.push('Good security with minor improvements possible');
    } else if (result.securityScore >= 50) {
      result.recommendations.push('Security needs improvement for better protection');
    } else {
      result.recommendations.push('Security requires immediate attention');
    }
  }
  
  /**
   * Quick security check for redirect chain analysis
   */
  async quickSecurityCheck(url: string): Promise<{
    httpsToHttp: boolean;
    safeBrowsingStatus: string;
    hasSecurityHeaders: boolean;
  }> {
    try {
      const analysis = await this.analyzeSecurity(url);
      
      return {
        httpsToHttp: analysis.flags.httpsToHttp,
        safeBrowsingStatus: analysis.flags.safeBrowsingStatus,
        hasSecurityHeaders: analysis.flags.securityHeaders.score > 0,
      };
    } catch (error) {
      logger.warn(`Quick security check failed for ${url}:`, error);
      return {
        httpsToHttp: false,
        safeBrowsingStatus: 'unknown',
        hasSecurityHeaders: false,
      };
    }
  }
}
