// api/sitemap.js
// Dynamic sitemap generator — fetches top anime from AniList
// Routes: /sitemap.xml (index) | /sitemap-anime.xml (all anime) | /sitemap-index.xml

const BASE = 'https://jsanime.site';
const ANILIST = 'https://graphql.anilist.co';

const STATIC_PAGES = [
  { url: BASE + '/',           priority: '1.0', changefreq: 'daily'   },
  { url: BASE + '/trending',  priority: '0.9', changefreq: 'hourly'  },
  { url: BASE + '/popular',   priority: '0.8', changefreq: 'daily'   },
  { url: BASE + '/top',       priority: '0.8', changefreq: 'weekly'  },
  { url: BASE + '/airing',    priority: '0.8', changefreq: 'hourly'  },
  { url: BASE + '/explore',   priority: '0.7', changefreq: 'daily'   },
  { url: BASE + '/schedule',  priority: '0.7', changefreq: 'hourly'  },
  { url: BASE + '/contact',   priority: '0.4', changefreq: 'monthly' },
  { url: BASE + '/dmca',      priority: '0.3', changefreq: 'monthly' },
  { url: BASE + '/privacy',   priority: '0.3', changefreq: 'monthly' },
];

async function fetchAnimeList(sort, page = 1, perPage = 50, status = null) {
  const query = `
    query($page:Int,$perPage:Int,$sort:[MediaSort],$status:MediaStatus){
      Page(page:$page,perPage:$perPage){
        pageInfo{hasNextPage lastPage}
        media(type:ANIME,sort:$sort,status:$status,isAdult:false){
          id title{english romaji} genres season seasonYear
          averageScore popularity episodes status
          coverImage{large}
          updatedAt
        }
      }
    }
  `;
  const vars = { page, perPage, sort: [sort], ...(status ? { status } : {}) };
  const r = await fetch(ANILIST, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
    body: JSON.stringify({ query, variables: vars }),
  });
  const d = await r.json();
  return d.data?.Page || { media: [], pageInfo: { hasNextPage: false } };
}

async function getAllAnime() {
  const seen = new Set();
  const all  = [];

  // Fetch across multiple sort types to maximise coverage
  const jobs = [
    { sort: 'POPULARITY_DESC', pages: 10 },
    { sort: 'TRENDING_DESC',   pages: 6  },
    { sort: 'SCORE_DESC',      pages: 6  },
    { sort: 'TRENDING_DESC',   pages: 4, status: 'RELEASING' },
    { sort: 'START_DATE_DESC', pages: 4  },
  ];

  for (const job of jobs) {
    for (let p = 1; p <= job.pages; p++) {
      try {
        const data = await fetchAnimeList(job.sort, p, 50, job.status || null);
        for (const a of data.media || []) {
          if (!seen.has(a.id)) {
            seen.add(a.id);
            all.push(a);
          }
        }
        if (!data.pageInfo?.hasNextPage) break;
        await new Promise(r => setTimeout(r, 250)); // gentle rate limit
      } catch { break; }
    }
  }
  return all;
}

function escape(str) {
  return (str || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

function animeUrl(id, title) {
  const slug = (title||'').toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'');
  return slug ? `${BASE}/anime/${id}/${slug}` : `${BASE}/anime/${id}`;
}

function animeXml(a) {
  const title      = escape(a.title?.english || a.title?.romaji || '');
  const rawTitle   = a.title?.english || a.title?.romaji || '';
  const url        = escape(animeUrl(a.id, rawTitle));
  const lastmod    = a.updatedAt
    ? new Date(a.updatedAt * 1000).toISOString().split('T')[0]
    : new Date().toISOString().split('T')[0];
  const priority   = a.popularity > 50000 ? '0.9'
                   : a.popularity > 10000 ? '0.8'
                   : a.popularity > 1000  ? '0.7' : '0.6';
  const changefreq = a.status === 'RELEASING' ? 'daily' : 'weekly';
  const image      = a.coverImage?.large ? escape(a.coverImage.large) : null;

  return [
    '  <url>',
    `    <loc>${url}</loc>`,
    `    <lastmod>${lastmod}</lastmod>`,
    `    <changefreq>${changefreq}</changefreq>`,
    `    <priority>${priority}</priority>`,
    image ? [
      '    <image:image>',
      `      <image:loc>${image}</image:loc>`,
      `      <image:title>${title}</image:title>`,
      '    </image:image>',
    ].join('\n') : '',
    '  </url>',
  ].filter(Boolean).join('\n');
}

function staticXml() {
  const today = new Date().toISOString().split('T')[0];
  return STATIC_PAGES.map(p => [
    '  <url>',
    `    <loc>${escape(p.url)}</loc>`,
    `    <lastmod>${today}</lastmod>`,
    `    <changefreq>${p.changefreq}</changefreq>`,
    `    <priority>${p.priority}</priority>`,
    '  </url>',
  ].join('\n')).join('\n');
}

function sitemapIndex() {
  const today = new Date().toISOString().split('T')[0];
  return [
    '<?xml version="1.0" encoding="UTF-8"?>',
    '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
    '  <sitemap>',
    `    <loc>${BASE}/sitemap.xml</loc>`,
    `    <lastmod>${today}</lastmod>`,
    '  </sitemap>',
    '  <sitemap>',
    `    <loc>${BASE}/sitemap-anime.xml</loc>`,
    `    <lastmod>${today}</lastmod>`,
    '  </sitemap>',
    '</sitemapindex>',
  ].join('\n');
}

module.exports = async function handler(req, res) {
  const type = (req.query?.type || (req.url?.includes('type=anime') ? 'anime'
              : req.url?.includes('type=index') ? 'index' : 'static'));

  res.setHeader('Content-Type', 'application/xml; charset=utf-8');
  res.setHeader('Cache-Control', 'public, max-age=3600, stale-while-revalidate=86400');

  try {
    if (type === 'index') {
      res.status(200).send(sitemapIndex());
      return;
    }

    if (type === 'anime') {
      const animes = await getAllAnime();
      const xml = [
        '<?xml version="1.0" encoding="UTF-8"?>',
        '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"',
        '        xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">',
        animes.map(animeXml).join('\n'),
        '</urlset>',
      ].join('\n');
      res.status(200).send(xml);
      return;
    }

    // Default: static pages sitemap
    const xml = [
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
      staticXml(),
      '</urlset>',
    ].join('\n');
    res.status(200).send(xml);

  } catch (err) {
    console.error('Sitemap error:', err.message);
    res.status(500).send('<?xml version="1.0"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>');
  }
};
