const fetch = require('node-fetch');
const fs = require('fs').promises;
const path = require('path');
const sharp = require('sharp');

class LogoFetcher {
  constructor() {
    this.cacheDir = path.join(__dirname, '../../cache/logos');
    this.cacheDuration = 30 * 24 * 60 * 60 * 1000; // 30 days in milliseconds
    this.ensureCacheDir();
  }

  async ensureCacheDir() {
    try {
      await fs.mkdir(this.cacheDir, { recursive: true });
    } catch (error) {
      console.error('Error creating cache directory:', error);
    }
  }

  // Get domain from product name
  getDomain(productName) {
    // Common product to domain mappings
    const domainMap = {
      'semrush': 'semrush.com',
      'ahrefs': 'ahrefs.com',
      'monday': 'monday.com',
      'asana': 'asana.com',
      'shopify': 'shopify.com',
      'woocommerce': 'woocommerce.com',
      'wordpress': 'wordpress.com',
      'slack': 'slack.com',
      'notion': 'notion.so',
      'trello': 'trello.com',
      'jira': 'atlassian.com',
      'figma': 'figma.com',
      'canva': 'canva.com',
      'mailchimp': 'mailchimp.com',
      'hubspot': 'hubspot.com',
      'salesforce': 'salesforce.com',
      'zendesk': 'zendesk.com',
      'intercom': 'intercom.com',
      'stripe': 'stripe.com',
      'paypal': 'paypal.com',
      'zoom': 'zoom.us',
      'dropbox': 'dropbox.com',
      'google': 'google.com',
      'microsoft': 'microsoft.com',
      'apple': 'apple.com',
      'adobe': 'adobe.com',
      'github': 'github.com',
      'gitlab': 'gitlab.com',
      'bitbucket': 'bitbucket.org',
      'aws': 'aws.amazon.com',
      'azure': 'azure.microsoft.com',
      'gcp': 'cloud.google.com',
      'netlify': 'netlify.com',
      'vercel': 'vercel.com',
      'heroku': 'heroku.com'
    };

    // If we have a mapping, use it
    if (domainMap[productName.toLowerCase()]) {
      return domainMap[productName.toLowerCase()];
    }

    // Otherwise, assume it's productname.com
    return `${productName.toLowerCase()}.com`;
  }

  // Get cache file path
  getCachePath(productName) {
    return path.join(this.cacheDir, `${productName.toLowerCase()}.png`);
  }

  // Check if cache is valid
  async isCacheValid(cachePath) {
    try {
      const stats = await fs.stat(cachePath);
      const age = Date.now() - stats.mtimeMs;
      return age < this.cacheDuration;
    } catch (error) {
      return false;
    }
  }

  // Fetch from Clearbit
  async fetchFromClearbit(domain) {
    try {
      const url = `https://logo.clearbit.com/${domain}`;
      const response = await fetch(url, {
        headers: {
          'User-Agent': 'Mozilla/5.0 (compatible; CompareKit/1.0)'
        },
        timeout: 5000
      });

      if (response.ok) {
        const buffer = await response.buffer();
        return buffer;
      }

      return null;
    } catch (error) {
      console.log(`Clearbit fetch failed for ${domain}:`, error.message);
      return null;
    }
  }

  // Fetch from Brandfetch
  async fetchFromBrandfetch(domain) {
    try {
      const apiKey = process.env.BRANDFETCH_API_KEY;
      if (!apiKey) {
        console.log('Brandfetch API key not configured');
        return null;
      }

      const url = `https://api.brandfetch.io/v2/brands/${domain}`;
      const response = await fetch(url, {
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'User-Agent': 'Mozilla/5.0 (compatible; CompareKit/1.0)'
        },
        timeout: 5000
      });

      if (response.ok) {
        const data = await response.json();

        // Get the logo URL from the response
        if (data.logos && data.logos.length > 0) {
          const logoUrl = data.logos[0].formats.find(f => f.format === 'png')?.src ||
                         data.logos[0].formats[0].src;

          // Download the logo
          const logoResponse = await fetch(logoUrl, { timeout: 5000 });
          if (logoResponse.ok) {
            return await logoResponse.buffer();
          }
        }
      }

      return null;
    } catch (error) {
      console.log(`Brandfetch fetch failed for ${domain}:`, error.message);
      return null;
    }
  }

  // Convert SVG to PNG using Sharp
  async convertToPNG(buffer) {
    try {
      // Try to convert to PNG
      const pngBuffer = await sharp(buffer)
        .png()
        .resize(800, 800, {
          fit: 'inside',
          withoutEnlargement: true,
          background: { r: 0, g: 0, b: 0, alpha: 0 }
        })
        .toBuffer();

      return pngBuffer;
    } catch (error) {
      console.log('SVG conversion failed:', error.message);
      return buffer; // Return original if conversion fails
    }
  }

  // Process and optimize logo
  async processLogo(buffer) {
    try {
      // Resize and optimize
      const processed = await sharp(buffer)
        .resize(800, 800, {
          fit: 'inside',
          withoutEnlargement: true,
          background: { r: 0, g: 0, b: 0, alpha: 0 }
        })
        .png()
        .toBuffer();

      return processed;
    } catch (error) {
      console.error('Logo processing failed:', error);
      return buffer;
    }
  }

  // Main fetch method
  async fetchLogo(productName) {
    const cachePath = this.getCachePath(productName);

    // Check cache first
    if (await this.isCacheValid(cachePath)) {
      try {
        const cached = await fs.readFile(cachePath);
        console.log(`✓ Logo loaded from cache: ${productName}`);
        return cached;
      } catch (error) {
        console.log('Cache read failed, fetching fresh logo');
      }
    }

    // Get domain
    const domain = this.getDomain(productName);
    console.log(`Fetching logo for ${productName} (${domain})...`);

    // Try Clearbit first
    let logoBuffer = await this.fetchFromClearbit(domain);

    // Fallback to Brandfetch
    if (!logoBuffer) {
      console.log('Trying Brandfetch...');
      logoBuffer = await this.fetchFromBrandfetch(domain);
    }

    // If still no logo, create a placeholder
    if (!logoBuffer) {
      console.log(`No logo found for ${productName}, creating placeholder`);
      return await this.createPlaceholder(productName);
    }

    // Process the logo
    const processedLogo = await this.processLogo(logoBuffer);

    // Save to cache
    try {
      await fs.writeFile(cachePath, processedLogo);
      console.log(`✓ Logo cached: ${productName}`);
    } catch (error) {
      console.error('Failed to cache logo:', error);
    }

    return processedLogo;
  }

  // Create a placeholder logo
  async createPlaceholder(productName) {
    const size = 800;
    const canvas = require('canvas').createCanvas(size, size);
    const ctx = canvas.getContext('2d');

    // Background
    ctx.fillStyle = '#6366F1';
    ctx.fillRect(0, 0, size, size);

    // Text
    const initials = productName.substring(0, 2).toUpperCase();
    ctx.fillStyle = '#FFFFFF';
    ctx.font = 'bold 300px Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(initials, size / 2, size / 2);

    return canvas.toBuffer('image/png');
  }

  // Batch fetch logos
  async fetchLogos(productNames) {
    const logos = {};

    for (const name of productNames) {
      logos[name] = await this.fetchLogo(name);
    }

    return logos;
  }

  // Clear cache
  async clearCache() {
    try {
      const files = await fs.readdir(this.cacheDir);
      for (const file of files) {
        await fs.unlink(path.join(this.cacheDir, file));
      }
      console.log('Cache cleared');
    } catch (error) {
      console.error('Error clearing cache:', error);
    }
  }

  // Get cache stats
  async getCacheStats() {
    try {
      const files = await fs.readdir(this.cacheDir);
      const stats = {
        count: files.length,
        files: []
      };

      for (const file of files) {
        const filePath = path.join(this.cacheDir, file);
        const fileStat = await fs.stat(filePath);
        stats.files.push({
          name: file,
          size: fileStat.size,
          modified: fileStat.mtime
        });
      }

      return stats;
    } catch (error) {
      console.error('Error getting cache stats:', error);
      return { count: 0, files: [] };
    }
  }
}

module.exports = LogoFetcher;
