/**
 * Ahrefs API v3 Route
 * Base URL: https://api.ahrefs.com/v3
 * Auth: Bearer token in Authorization header
 * Docs: https://docs.ahrefs.com/docs/api/reference/introduction
 *
 * Endpoints used:
 *   GET /site-explorer/organic-keywords   — keyword positions + movement
 *   GET /site-explorer/metrics            — domain overview (DR, traffic, keywords)
 *   GET /site-explorer/metrics-history    — historical organic traffic
 *   GET /site-explorer/top-pages          — top pages by organic traffic
 *   GET /site-explorer/backlinks-stats    — backlink summary
 *   GET /site-explorer/refdomains         — referring domains
 *   GET /keywords-explorer/overview       — keyword metrics (volume, KD, CPC)
 *   GET /site-explorer/competitors-overview — organic competitors
 */

const express = require('express');
const axios = require('axios');
const NodeCache = require('node-cache');

const router = express.Router();
const cache = new NodeCache({ stdTTL: parseInt(process.env.CACHE_TTL) || 300 });

const AH = axios.create({
  baseURL: 'https://api.ahrefs.com/v3',
  headers: {
    Authorization: `Bearer ${process.env.AHREFS_API_KEY}`,
    'Content-Type': 'application/json',
  },
});

// Ahrefs rate limit: 60 req/min. We add a small delay helper for bulk calls.
const sleep = (ms) => new Promise(r => setTimeout(r, ms));

function today() {
  return new Date().toISOString().split('T')[0];
}
function daysAgo(n) {
  const d = new Date();
  d.setDate(d.getDate() - n);
  return d.toISOString().split('T')[0];
}

// ── GET /api/ahrefs/overview?domain= ─────────────────────────
// Domain Rating, organic traffic estimate, total keywords, backlinks
router.get('/overview', async (req, res, next) => {
  const { domain } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_overview_${domain}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    const [metricsResp, backlinkResp] = await Promise.all([
      AH.get('/site-explorer/metrics', {
        params: { target: domain, date: today(), output: 'json' },
      }),
      AH.get('/site-explorer/backlinks-stats', {
        params: { target: domain, date: today(), mode: 'domain', output: 'json' },
      }),
    ]);

    const m = metricsResp.data?.metrics || metricsResp.data || {};
    const b = backlinkResp.data?.stats || backlinkResp.data || {};

    const result = {
      domain,
      domainRating: m.domain_rating ?? null,
      urlRating: m.url_rating ?? null,
      organicTraffic: m.org_traffic ?? null,
      organicKeywords: m.org_keywords ?? null,
      backlinks: b.backlinks ?? null,
      refDomains: b.refdomains ?? null,
      linkedDomains: b.linked_domains ?? null,
    };

    cache.set(cacheKey, result);
    res.json(result);
  } catch (err) {
    if (!process.env.AHREFS_API_KEY || process.env.AHREFS_API_KEY.includes('your_')) {
      return res.json(getMockOverview(domain));
    }
    next(err);
  }
});

// ── GET /api/ahrefs/keywords?domain=&limit=50&country=us ──────
// Organic keyword positions with previous-period comparison + movement
router.get('/keywords', async (req, res, next) => {
  const { domain, limit = 50, country = 'us' } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_kw_${domain}_${limit}_${country}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    // Current period keywords
    const resp = await AH.get('/site-explorer/organic-keywords', {
      params: {
        target: domain,
        country,
        date: today(),
        date_compared: daysAgo(28),
        limit: parseInt(limit),
        order_by: 'traffic:desc',
        output: 'json',
        // Request fields we need
        select: [
          'keyword', 'volume', 'keyword_difficulty', 'cpc',
          'position', 'position_compared_to', 'traffic',
          'traffic_compared_to', 'url', 'serp_features',
        ].join(','),
      },
    });

    const rows = resp.data?.keywords || resp.data?.data || [];

    const keywords = rows.map(r => {
      const pos = r.position ?? null;
      const prevPos = r.position_compared_to ?? null;
      const delta = (pos !== null && prevPos !== null) ? prevPos - pos : null;

      return {
        keyword: r.keyword,
        position: pos,
        prevPosition: prevPos,
        positionDelta: delta !== null ? parseFloat(delta.toFixed(1)) : null,
        movement: delta === null ? 'new' : delta > 0.5 ? 'up' : delta < -0.5 ? 'down' : 'stable',
        searchVolume: r.volume ?? 0,
        keywordDifficulty: r.keyword_difficulty ?? null,
        cpc: r.cpc ?? null,
        traffic: r.traffic ?? null,
        prevTraffic: r.traffic_compared_to ?? null,
        url: r.url ?? '',
        // Ahrefs doesn't return 7-day history per keyword in this endpoint,
        // so we build a synthetic mini-history from pos + prevPos for sparklines
        positionHistory: buildMiniHistory(pos, prevPos),
      };
    });

    cache.set(cacheKey, keywords);
    res.json(keywords);
  } catch (err) {
    if (!process.env.AHREFS_API_KEY || process.env.AHREFS_API_KEY.includes('your_')) {
      return res.json(getMockKeywords(domain));
    }
    next(err);
  }
});

// ── GET /api/ahrefs/history?domain=&days=90 ──────────────────
// Daily organic traffic + keyword count history for the chart
router.get('/history', async (req, res, next) => {
  const { domain, days = 90 } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_hist_${domain}_${days}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    const resp = await AH.get('/site-explorer/metrics-history', {
      params: {
        target: domain,
        date_from: daysAgo(parseInt(days)),
        date_to: today(),
        history_grouping: 'weekly',
        output: 'json',
      },
    });

    const rows = resp.data?.metrics || resp.data?.data || [];
    const history = rows.map(r => ({
      date: r.date,
      organicTraffic: r.org_traffic ?? 0,
      organicKeywords: r.org_keywords ?? 0,
      domainRating: r.domain_rating ?? null,
    }));

    cache.set(cacheKey, history);
    res.json(history);
  } catch (err) {
    if (!process.env.AHREFS_API_KEY || process.env.AHREFS_API_KEY.includes('your_')) {
      return res.json(getMockHistory(days));
    }
    next(err);
  }
});

// ── GET /api/ahrefs/pages?domain=&limit=20 ───────────────────
// Top pages by organic traffic
router.get('/pages', async (req, res, next) => {
  const { domain, limit = 20, country = 'us' } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_pages_${domain}_${limit}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    const resp = await AH.get('/site-explorer/top-pages', {
      params: {
        target: domain,
        country,
        date: today(),
        limit: parseInt(limit),
        order_by: 'traffic:desc',
        output: 'json',
        select: 'url,traffic,keywords,top_keyword,top_keyword_volume,top_keyword_position',
      },
    });

    const rows = resp.data?.pages || resp.data?.data || [];
    const pages = rows.map(r => ({
      page: (r.url || '').replace(`https://${domain}`, '').replace(`http://${domain}`, '') || '/',
      url: r.url,
      traffic: r.traffic ?? 0,
      keywords: r.keywords ?? 0,
      topKeyword: r.top_keyword ?? null,
      topKeywordVolume: r.top_keyword_volume ?? null,
      topKeywordPosition: r.top_keyword_position ?? null,
    }));

    cache.set(cacheKey, pages);
    res.json(pages);
  } catch (err) {
    if (!process.env.AHREFS_API_KEY || process.env.AHREFS_API_KEY.includes('your_')) {
      return res.json(getMockPages(domain));
    }
    next(err);
  }
});

// ── GET /api/ahrefs/backlinks?domain=&limit=20 ───────────────
// Top backlinks with DR, anchor text, follow/nofollow
router.get('/backlinks', async (req, res, next) => {
  const { domain, limit = 20 } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_bl_${domain}_${limit}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    const resp = await AH.get('/site-explorer/backlinks', {
      params: {
        target: domain,
        mode: 'domain',
        limit: parseInt(limit),
        order_by: 'domain_rating_source:desc',
        output: 'json',
        select: 'url_from,title,domain_from,domain_rating_source,url_rating_source,anchor,nofollow,first_seen,last_seen',
      },
    });

    const rows = resp.data?.backlinks || resp.data?.data || [];
    const backlinks = rows.map(r => ({
      urlFrom: r.url_from,
      domain: r.domain_from,
      title: r.title,
      domainRating: r.domain_rating_source ?? null,
      urlRating: r.url_rating_source ?? null,
      anchor: r.anchor ?? '',
      follow: !r.nofollow,
      firstSeen: r.first_seen,
      lastSeen: r.last_seen,
    }));

    cache.set(cacheKey, backlinks);
    res.json(backlinks);
  } catch (err) {
    next(err);
  }
});

// ── GET /api/ahrefs/competitors?domain=&limit=10 ─────────────
// Top organic competitors with overlap data
router.get('/competitors', async (req, res, next) => {
  const { domain, limit = 10 } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_comp_${domain}_${limit}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    const resp = await AH.get('/site-explorer/competitors-overview', {
      params: {
        target: domain,
        date: today(),
        limit: parseInt(limit),
        output: 'json',
      },
    });

    const rows = resp.data?.competitors || resp.data?.data || [];
    const competitors = rows.map(r => ({
      domain: r.competitor ?? r.domain,
      domainRating: r.domain_rating ?? null,
      commonKeywords: r.common_keywords ?? null,
      organicKeywords: r.organic_keywords ?? null,
      organicTraffic: r.organic_traffic ?? null,
      competitionLevel: r.competition_level ?? null,
    }));

    cache.set(cacheKey, competitors);
    res.json(competitors);
  } catch (err) {
    next(err);
  }
});

// ── GET /api/ahrefs/refdomains?domain=&limit=20 ──────────────
// Top referring domains
router.get('/refdomains', async (req, res, next) => {
  const { domain, limit = 20 } = req.query;
  if (!domain) return res.status(400).json({ error: 'domain param required' });

  const cacheKey = `ah_rfd_${domain}_${limit}`;
  const cached = cache.get(cacheKey);
  if (cached) return res.json(cached);

  try {
    const resp = await AH.get('/site-explorer/refdomains', {
      params: {
        target: domain,
        mode: 'domain',
        limit: parseInt(limit),
        order_by: 'domain_rating:desc',
        output: 'json',
        select: 'domain,domain_rating,backlinks,linked_domains,first_seen,last_visited,dofollow_linked_domains',
      },
    });

    const rows = resp.data?.refdomains || resp.data?.data || [];
    const refdomains = rows.map(r => ({
      domain: r.domain,
      domainRating: r.domain_rating ?? null,
      backlinks: r.backlinks ?? 0,
      dofollow: r.dofollow_linked_domains ?? null,
      firstSeen: r.first_seen,
    }));

    cache.set(cacheKey, refdomains);
    res.json(refdomains);
  } catch (err) {
    next(err);
  }
});

// ── Helpers ───────────────────────────────────────────────────

function buildMiniHistory(pos, prevPos) {
  // Generates a plausible 7-point sparkline from current + previous position
  if (!pos) return Array(7).fill(null);
  if (!prevPos) return Array(7).fill(pos);
  const diff = pos - prevPos;
  return Array.from({ length: 7 }, (_, i) => {
    const t = i / 6;
    const noise = (Math.random() - 0.5) * Math.max(1, Math.abs(diff) * 0.3);
    return Math.max(1, Math.round(prevPos + diff * t + noise));
  });
}

// ── Mock data (used when AHREFS_API_KEY is not set, for dev/demo) ─
function getMockOverview(domain) {
  return { domain, domainRating: 58, urlRating: 32, organicTraffic: 24800, organicKeywords: 4120, backlinks: 18400, refDomains: 890, linkedDomains: 240 };
}

function getMockKeywords(domain) {
  return [
    { keyword: 'best crm software', position: 2, prevPosition: 5, positionDelta: 3, movement: 'up', searchVolume: 12100, keywordDifficulty: 72, cpc: 8.5, traffic: 1820, url: `https://${domain}/crm`, positionHistory: [5,5,4,4,3,3,2] },
    { keyword: 'project management app', position: 4, prevPosition: 3, positionDelta: -1, movement: 'down', searchVolume: 9800, keywordDifficulty: 68, cpc: 6.2, traffic: 940, url: `https://${domain}/pm`, positionHistory: [3,3,3,4,4,3,4] },
    { keyword: 'free invoice template', position: 8, prevPosition: 14, positionDelta: 6, movement: 'up', searchVolume: 6500, keywordDifficulty: 41, cpc: 3.1, traffic: 610, url: `https://${domain}/invoice`, positionHistory: [14,13,11,10,9,9,8] },
    { keyword: 'saas pricing models', position: 11, prevPosition: 7, positionDelta: -4, movement: 'down', searchVolume: 4200, keywordDifficulty: 55, cpc: 5.8, traffic: 280, url: `https://${domain}/pricing`, positionHistory: [7,7,8,9,10,11,11] },
    { keyword: 'customer onboarding', position: 23, prevPosition: 24, positionDelta: 1, movement: 'stable', searchVolume: 3100, keywordDifficulty: 38, cpc: 4.4, traffic: 90, url: `https://${domain}/onboarding`, positionHistory: [24,25,24,23,24,24,23] },
    { keyword: 'seo audit checklist', position: 3, prevPosition: 9, positionDelta: 6, movement: 'up', searchVolume: 5500, keywordDifficulty: 44, cpc: 4.0, traffic: 820, url: `https://${domain}/seo`, positionHistory: [9,8,7,6,5,4,3] },
    { keyword: 'b2b lead generation', position: 17, prevPosition: 12, positionDelta: -5, movement: 'down', searchVolume: 7200, keywordDifficulty: 62, cpc: 9.1, traffic: 210, url: `https://${domain}/leads`, positionHistory: [12,12,13,14,15,16,17] },
    { keyword: 'email marketing tool', position: 6, prevPosition: 6, positionDelta: 0, movement: 'stable', searchVolume: 8700, keywordDifficulty: 70, cpc: 7.3, traffic: 740, url: `https://${domain}/email`, positionHistory: [6,7,6,6,6,7,6] },
    { keyword: 'content marketing tips', position: 1, prevPosition: 2, positionDelta: 1, movement: 'up', searchVolume: 11300, keywordDifficulty: 51, cpc: 5.5, traffic: 2100, url: `https://${domain}/content`, positionHistory: [2,2,2,1,1,2,1] },
    { keyword: 'hr software comparison', position: 5, prevPosition: null, positionDelta: null, movement: 'new', searchVolume: 4400, keywordDifficulty: 47, cpc: 6.8, traffic: 580, url: `https://${domain}/hr`, positionHistory: [null,null,null,null,12,8,5] },
  ];
}

function getMockHistory(days) {
  const result = [];
  let traffic = 18000;
  const n = Math.min(parseInt(days) / 7, 13);
  for (let i = 0; i < n; i++) {
    const d = new Date(); d.setDate(d.getDate() - (n - i) * 7);
    traffic = Math.max(10000, traffic + (Math.random() - 0.4) * 1200);
    result.push({ date: d.toISOString().split('T')[0], organicTraffic: Math.round(traffic), organicKeywords: Math.round(3800 + i * 40), domainRating: 58 });
  }
  return result;
}

function getMockPages(domain) {
  return [
    { page: '/crm', url: `https://${domain}/crm`, traffic: 4200, keywords: 312, topKeyword: 'best crm software', topKeywordVolume: 12100, topKeywordPosition: 2 },
    { page: '/content', url: `https://${domain}/content`, traffic: 3100, keywords: 241, topKeyword: 'content marketing tips', topKeywordVolume: 11300, topKeywordPosition: 1 },
    { page: '/email', url: `https://${domain}/email`, traffic: 2800, keywords: 198, topKeyword: 'email marketing tool', topKeywordVolume: 8700, topKeywordPosition: 6 },
    { page: '/invoice', url: `https://${domain}/invoice`, traffic: 1900, keywords: 87, topKeyword: 'free invoice template', topKeywordVolume: 6500, topKeywordPosition: 8 },
    { page: '/seo', url: `https://${domain}/seo`, traffic: 1600, keywords: 143, topKeyword: 'seo audit checklist', topKeywordVolume: 5500, topKeywordPosition: 3 },
  ];
}

module.exports = router;
