import * as cheerio from 'cheerio';

interface ScrapeResult {
  title: string;
  thumbnailUrl: string;
  problemStatement: string;
  solution: string;
}

interface PageElement {
  type: 'heading' | 'content';
  tagName: string;
  text: string;
  problemScore: number;
  solutionScore: number;
}

export class ScraperService {
  private problemKeywords: Record<string, number> = {
    'problem statement': 1.0,
    'challenges': 0.9,
    'challenge': 0.9,
    'problem': 0.9,
    'pain point': 0.9,
    'issue': 0.8,
    'background': 0.6,
    'context': 0.5,
    'objective': 0.6,
  };

  private solutionKeywords: Record<string, number> = {
    'suggested solution': 1.0,
    'solution': 0.9,
    'approach': 0.8,
    'implementation': 0.7,
    'architecture': 0.8,
    'technology': 0.6,
  };

  private stopKeywords: string[] = [
    'result',
    'conclusion',
    'roi',
    'future',
    'roadmap',
    'benefit',
    'collaboration',
    'support'
  ];

  private getCategoryScore(text: string, keywords: Record<string, number>): number {
    const lowerText = text.toLowerCase();
    let maxScore = 0;
    for (const [kw, score] of Object.entries(keywords)) {
      if (lowerText.includes(kw)) {
        maxScore = Math.max(maxScore, score);
      }
    }
    return maxScore;
  }

  public async scrapeCaseStudy(url: string): Promise<ScrapeResult> {
    try {
      const response = await fetch(url, {
        headers: {
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
        }
      });

      if (!response.ok) {
        throw new Error(`Failed to fetch page. Status: ${response.status}`);
      }

      const html = await response.text();
      const $ = cheerio.load(html);

      // Extract Title
      let title = $('meta[property="og:title"]').attr('content') || 
                  $('meta[name="twitter:title"]').attr('content') || 
                  $('title').text() || 
                  $('h1').first().text() || 
                  '';
      
      title = title.replace(/\s*[-|]\s*Tech4Biz.*$/i, '').trim();

      // Extract Banner Image/Thumbnail
      const thumbnailUrl = $('meta[property="og:image"]').attr('content') || 
                           $('meta[name="twitter:image"]').attr('content') || 
                           '';

      const elements = $('h1, h2, h3, h4, h5, h6, p, ul, ol');
      const pageElements: PageElement[] = [];

      elements.each((_, el) => {
        const $el = $(el);
        const tagName = el.name.toLowerCase();
        const text = $el.text().trim();
        if (!text) return;

        // Skip copyright and common footer elements
        if (text.toLowerCase().includes('copyright reserved')) return;

        if (tagName.startsWith('h') && text.length < 65) {
          const problemScore = this.getCategoryScore(text, this.problemKeywords);
          const solutionScore = this.getCategoryScore(text, this.solutionKeywords);
          pageElements.push({
            type: 'heading',
            tagName,
            text,
            problemScore,
            solutionScore
          });
        } else {
          let formattedText = '';
          if (tagName === 'ul' || tagName === 'ol') {
            const listItems: string[] = [];
            $el.find('li').each((_, li) => {
              const liText = $(li).text().trim();
              if (liText) {
                listItems.push(`• ${liText}`);
              }
            });
            if (listItems.length > 0) {
              formattedText = listItems.join('\n');
            }
          } else {
            if (text.length > 10) {
              formattedText = text;
            }
          }

          if (formattedText) {
            pageElements.push({
              type: 'content',
              tagName,
              text: formattedText,
              problemScore: 0,
              solutionScore: 0
            });
          }
        }
      });

      // Find the best indices
      let bestProblemIdx = -1;
      let maxProblemScore = 0.4;
      let bestSolutionIdx = -1;
      let maxSolutionScore = 0.4;

      pageElements.forEach((el, idx) => {
        if (el.type === 'heading') {
          if (el.problemScore > maxProblemScore) {
            maxProblemScore = el.problemScore;
            bestProblemIdx = idx;
          }
          if (el.solutionScore > maxSolutionScore) {
            maxSolutionScore = el.solutionScore;
            bestSolutionIdx = idx;
          }
        }
      });

      // Fallback searches
      if (bestProblemIdx === -1) {
        bestProblemIdx = pageElements.findIndex(el => 
          el.type === 'heading' && 
          (el.text.toLowerCase().includes('background') || el.text.toLowerCase().includes('overview'))
        );
      }

      if (bestSolutionIdx === -1) {
        bestSolutionIdx = pageElements.findIndex(el => 
          el.type === 'heading' && 
          (el.text.toLowerCase().includes('implementation') || el.text.toLowerCase().includes('results') || el.text.toLowerCase().includes('benefits') || el.text.toLowerCase().includes('components'))
        );
      }

      const gatherContent = (startIdx: number, otherIdx: number, isProblem: boolean): string => {
        if (startIdx === -1) return '';

        const collected: string[] = [];
        let contentCount = 0;

        for (let i = startIdx + 1; i < pageElements.length; i++) {
          if (i === otherIdx) break;

          const el = pageElements[i];
          if (el.type === 'heading') {
            const lowerText = el.text.toLowerCase();

            // Stop if we hit the other major category heading
            if (isProblem && el.solutionScore >= 0.8) break;
            if (!isProblem && el.problemScore >= 0.8) break;

            // Stop if we hit a stop keyword
            const matchesStop = this.stopKeywords.some(kw => lowerText.includes(kw));
            if (matchesStop) break;

            // Include subheading formatting
            collected.push(`**${el.text}**`);
          } else {
            // Simple de-duplication for consecutive identical elements
            if (collected[collected.length - 1] !== el.text) {
              collected.push(el.text);
              contentCount++;
            }
            if (contentCount >= 5) break;
          }
        }

        return collected.join('\n\n');
      };

      const problemStatement = gatherContent(bestProblemIdx, bestSolutionIdx, true);
      const solution = gatherContent(bestSolutionIdx, bestProblemIdx, false);

      return {
        title,
        thumbnailUrl,
        problemStatement,
        solution
      };
    } catch (error: any) {
      console.error('[SCRAPE ERROR] Failed to scrape case study:', error.message);
      throw new Error(`Scraping failed: ${error.message}`);
    }
  }
}

