/**
 * SEO Analyzer Service for Redirect Intelligence v2
 * 
 * Analyzes SEO-related aspects of redirects and final destinations
 */

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

export interface RobotsAnalysis {
  status: 'found' | 'not_found' | 'error';
  rules: {
    userAgent: string;
    allow: string[];
    disallow: string[];
    crawlDelay?: number;
  }[];
  sitemaps: string[];
}

export interface MetaTagsAnalysis {
  title?: string;
  description?: string;
  robots?: string;
  canonical?: string;
  viewport?: string;
  openGraph: {
    title?: string;
    description?: string;
    image?: string;
    url?: string;
    type?: string;
  };
  twitter: {
    card?: string;
    title?: string;
    description?: string;
    image?: string;
  };
}

export interface SEOFlags {
  robotsTxtStatus: 'found' | 'not_found' | 'error';
  robotsTxtRules: RobotsAnalysis;
  metaRobots?: string;
  canonicalUrl?: string;
  sitemapPresent: boolean;
  noindex: boolean;
  nofollow: boolean;
  hasTitle: boolean;
  hasDescription: boolean;
  titleLength?: number;
  descriptionLength?: number;
  openGraphPresent: boolean;
  twitterCardPresent: boolean;
}

export interface SEOAnalysisResult {
  url: string;
  flags: SEOFlags;
  metaTags: MetaTagsAnalysis;
  recommendations: string[];
  warnings: string[];
  score: number; // 0-100
}

export class SEOAnalyzerService {
  
  /**
   * Perform comprehensive SEO analysis
   */
  async analyzeSEO(url: string): Promise<SEOAnalysisResult> {
    logger.info(`Starting SEO analysis for: ${url}`);
    
    const result: SEOAnalysisResult = {
      url,
      flags: {
        robotsTxtStatus: 'not_found',
        robotsTxtRules: { status: 'not_found', rules: [], sitemaps: [] },
        sitemapPresent: false,
        noindex: false,
        nofollow: false,
        hasTitle: false,
        hasDescription: false,
        openGraphPresent: false,
        twitterCardPresent: false,
      },
      metaTags: {
        openGraph: {},
        twitter: {},
      },
      recommendations: [],
      warnings: [],
      score: 0,
    };
    
    try {
      // Analyze robots.txt
      const robotsAnalysis = await this.analyzeRobotsTxt(url);
      result.flags.robotsTxtStatus = robotsAnalysis.status;
      result.flags.robotsTxtRules = robotsAnalysis;
      result.flags.sitemapPresent = robotsAnalysis.sitemaps.length > 0;
      
      // Analyze page content
      const pageAnalysis = await this.analyzePageContent(url);
      result.metaTags = pageAnalysis.metaTags;
      result.flags = { ...result.flags, ...pageAnalysis.flags };
      
      // Generate recommendations and calculate score
      this.generateSEORecommendations(result);
      
      logger.info(`SEO analysis completed for: ${url}`, {
        score: result.score,
        robotsStatus: result.flags.robotsTxtStatus,
        hasTitle: result.flags.hasTitle,
        noindex: result.flags.noindex
      });
      
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Unknown SEO analysis error';
      result.warnings.push(`SEO analysis failed: ${errorMessage}`);
      logger.error(`SEO analysis failed for ${url}:`, error);
    }
    
    return result;
  }
  
  /**
   * Analyze robots.txt file
   */
  private async analyzeRobotsTxt(url: string): Promise<RobotsAnalysis> {
    try {
      const parsedUrl = new URL(url);
      const robotsUrl = `${parsedUrl.protocol}//${parsedUrl.host}/robots.txt`;
      
      const response = await axios.get(robotsUrl, {
        timeout: 5000,
        headers: {
          'User-Agent': 'RedirectIntelligence-Bot/2.0',
        },
      });
      
      const robotsContent = response.data;
      return this.parseRobotsTxt(robotsContent);
      
    } catch (error) {
      if (axios.isAxiosError(error) && error.response?.status === 404) {
        return { status: 'not_found', rules: [], sitemaps: [] };
      }
      
      logger.warn(`Failed to fetch robots.txt for ${url}:`, error);
      return { status: 'error', rules: [], sitemaps: [] };
    }
  }
  
  /**
   * Parse robots.txt content
   */
  private parseRobotsTxt(content: string): RobotsAnalysis {
    const lines = content.split('\n').map(line => line.trim());
    const rules: RobotsAnalysis['rules'] = [];
    const sitemaps: string[] = [];
    
    let currentRule: RobotsAnalysis['rules'][0] | null = null;
    
    for (const line of lines) {
      if (line.startsWith('#') || line === '') continue;
      
      const [directive, ...valueParts] = line.split(':');
      const value = valueParts.join(':').trim();
      
      switch (directive.toLowerCase()) {
        case 'user-agent':
          if (currentRule) {
            rules.push(currentRule);
          }
          currentRule = {
            userAgent: value,
            allow: [],
            disallow: [],
          };
          break;
          
        case 'allow':
          if (currentRule) {
            currentRule.allow.push(value);
          }
          break;
          
        case 'disallow':
          if (currentRule) {
            currentRule.disallow.push(value);
          }
          break;
          
        case 'crawl-delay':
          if (currentRule) {
            currentRule.crawlDelay = parseInt(value) || undefined;
          }
          break;
          
        case 'sitemap':
          sitemaps.push(value);
          break;
      }
    }
    
    if (currentRule) {
      rules.push(currentRule);
    }
    
    return {
      status: 'found',
      rules,
      sitemaps,
    };
  }
  
  /**
   * Analyze page content for meta tags and SEO elements
   */
  private async analyzePageContent(url: string): Promise<{
    metaTags: MetaTagsAnalysis;
    flags: Partial<SEOFlags>;
  }> {
    try {
      const response = await axios.get(url, {
        timeout: 10000,
        headers: {
          'User-Agent': 'RedirectIntelligence-Bot/2.0 (SEO Analysis)',
        },
        maxContentLength: 1024 * 1024, // 1MB limit
      });
      
      const html = response.data;
      return this.parseHTMLContent(html);
      
    } catch (error) {
      logger.warn(`Failed to fetch page content for ${url}:`, error);
      
      return {
        metaTags: { openGraph: {}, twitter: {} },
        flags: {
          hasTitle: false,
          hasDescription: false,
          noindex: false,
          nofollow: false,
          openGraphPresent: false,
          twitterCardPresent: false,
        },
      };
    }
  }
  
  /**
   * Parse HTML content for SEO elements
   */
  private parseHTMLContent(html: string): {
    metaTags: MetaTagsAnalysis;
    flags: Partial<SEOFlags>;
  } {
    const metaTags: MetaTagsAnalysis = {
      openGraph: {},
      twitter: {},
    };
    
    const flags: Partial<SEOFlags> = {
      hasTitle: false,
      hasDescription: false,
      noindex: false,
      nofollow: false,
      openGraphPresent: false,
      twitterCardPresent: false,
    };
    
    // Extract title
    const titleMatch = html.match(/<title[^>]*>(.*?)<\/title>/is);
    if (titleMatch) {
      metaTags.title = this.cleanText(titleMatch[1]);
      flags.hasTitle = true;
      flags.titleLength = metaTags.title.length;
    }
    
    // Extract meta tags
    const metaTagRegex = /<meta\s+([^>]*?)>/gi;
    let metaMatch;
    
    while ((metaMatch = metaTagRegex.exec(html)) !== null) {
      const attributes = this.parseAttributes(metaMatch[1]);
      
      // Standard meta tags
      if (attributes.name === 'description') {
        metaTags.description = attributes.content;
        flags.hasDescription = true;
        flags.descriptionLength = attributes.content?.length || 0;
      } else if (attributes.name === 'robots') {
        metaTags.robots = attributes.content;
        flags.metaRobots = attributes.content;
        
        if (attributes.content?.toLowerCase().includes('noindex')) {
          flags.noindex = true;
        }
        if (attributes.content?.toLowerCase().includes('nofollow')) {
          flags.nofollow = true;
        }
      } else if (attributes.name === 'viewport') {
        metaTags.viewport = attributes.content;
      }
      
      // Open Graph tags
      else if (attributes.property?.startsWith('og:')) {
        const ogProperty = attributes.property.substring(3);
        metaTags.openGraph[ogProperty as keyof typeof metaTags.openGraph] = attributes.content;
        flags.openGraphPresent = true;
      }
      
      // Twitter Card tags
      else if (attributes.name?.startsWith('twitter:')) {
        const twitterProperty = attributes.name.substring(8);
        metaTags.twitter[twitterProperty as keyof typeof metaTags.twitter] = attributes.content;
        flags.twitterCardPresent = true;
      }
    }
    
    // Extract canonical URL
    const canonicalMatch = html.match(/<link\s+([^>]*?)rel=['"]canonical['"][^>]*>/i);
    if (canonicalMatch) {
      const attributes = this.parseAttributes(canonicalMatch[1]);
      metaTags.canonical = attributes.href;
      flags.canonicalUrl = attributes.href;
    }
    
    return { metaTags, flags };
  }
  
  /**
   * Parse HTML attributes from a string
   */
  private parseAttributes(attributeString: string): Record<string, string> {
    const attributes: Record<string, string> = {};
    const attrRegex = /(\w+)=['"]([^'"]*)['"]/g;
    let match;
    
    while ((match = attrRegex.exec(attributeString)) !== null) {
      attributes[match[1].toLowerCase()] = match[2];
    }
    
    return attributes;
  }
  
  /**
   * Clean text content
   */
  private cleanText(text: string): string {
    return text.replace(/\s+/g, ' ').trim();
  }
  
  /**
   * Generate SEO recommendations and calculate score
   */
  private generateSEORecommendations(result: SEOAnalysisResult): void {
    let score = 100;
    
    // Title analysis
    if (!result.flags.hasTitle) {
      result.warnings.push('Missing page title');
      result.recommendations.push('Add a descriptive page title');
      score -= 15;
    } else if (result.flags.titleLength) {
      if (result.flags.titleLength < 30) {
        result.warnings.push('Title is too short');
        result.recommendations.push('Expand title to 30-60 characters for better SEO');
        score -= 5;
      } else if (result.flags.titleLength > 60) {
        result.warnings.push('Title is too long');
        result.recommendations.push('Shorten title to under 60 characters');
        score -= 5;
      }
    }
    
    // Description analysis
    if (!result.flags.hasDescription) {
      result.warnings.push('Missing meta description');
      result.recommendations.push('Add a meta description (150-160 characters)');
      score -= 10;
    } else if (result.flags.descriptionLength) {
      if (result.flags.descriptionLength < 120) {
        result.warnings.push('Meta description is too short');
        result.recommendations.push('Expand meta description to 150-160 characters');
        score -= 3;
      } else if (result.flags.descriptionLength > 160) {
        result.warnings.push('Meta description is too long');
        result.recommendations.push('Shorten meta description to under 160 characters');
        score -= 3;
      }
    }
    
    // Robots.txt analysis
    if (result.flags.robotsTxtStatus === 'not_found') {
      result.recommendations.push('Consider adding a robots.txt file');
      score -= 5;
    } else if (result.flags.robotsTxtStatus === 'error') {
      result.warnings.push('Robots.txt file has errors');
      result.recommendations.push('Fix robots.txt file errors');
      score -= 8;
    }
    
    // Sitemap analysis
    if (!result.flags.sitemapPresent) {
      result.recommendations.push('Add XML sitemap references to robots.txt');
      score -= 5;
    }
    
    // Indexing analysis
    if (result.flags.noindex) {
      result.warnings.push('Page is set to noindex');
      result.recommendations.push('Remove noindex if you want this page indexed');
      score -= 20;
    }
    
    // Social media optimization
    if (!result.flags.openGraphPresent) {
      result.recommendations.push('Add Open Graph meta tags for social media sharing');
      score -= 5;
    }
    
    if (!result.flags.twitterCardPresent) {
      result.recommendations.push('Add Twitter Card meta tags for Twitter sharing');
      score -= 3;
    }
    
    // Canonical URL
    if (!result.flags.canonicalUrl) {
      result.recommendations.push('Add canonical URL to prevent duplicate content issues');
      score -= 5;
    }
    
    result.score = Math.max(0, score);
    
    // Add overall recommendations
    if (result.score >= 90) {
      result.recommendations.push('Excellent SEO setup!');
    } else if (result.score >= 70) {
      result.recommendations.push('Good SEO with room for minor improvements');
    } else if (result.score >= 50) {
      result.recommendations.push('SEO needs improvement for better search visibility');
    } else {
      result.recommendations.push('SEO requires immediate attention');
    }
  }
  
  /**
   * Quick SEO check for redirect chain analysis
   */
  async quickSEOCheck(url: string): Promise<{
    noindex: boolean;
    nofollow: boolean;
    robotsBlocked: boolean;
    hasTitle: boolean;
  }> {
    try {
      const analysis = await this.analyzeSEO(url);
      
      // Check if robots.txt blocks crawlers
      const robotsBlocked = analysis.flags.robotsTxtRules.rules.some(rule => 
        rule.userAgent === '*' && rule.disallow.includes('/')
      );
      
      return {
        noindex: analysis.flags.noindex,
        nofollow: analysis.flags.nofollow,
        robotsBlocked,
        hasTitle: analysis.flags.hasTitle,
      };
    } catch (error) {
      logger.warn(`Quick SEO check failed for ${url}:`, error);
      return {
        noindex: false,
        nofollow: false,
        robotsBlocked: false,
        hasTitle: false,
      };
    }
  }
}
