const GOOGLE_FONTS_CSS_IMPORT_RE =
  /@import\s+url\(\s*['"]?(https:\/\/fonts\.googleapis\.com\/[^'")\s]+)['"]?\s*\)\s*;?/gi;
const GOOGLE_FONTS_LINK_RE =
  /<link\b[^>]*\bhref=['"](https:\/\/fonts\.googleapis\.com\/[^'"]+)['"][^>]*>/gi;

async function fetchStylesheet(url) {
  const response = await fetch(url, {
    headers: { 'User-Agent': 'TKMind-MindSpace/1.0' },
    signal: AbortSignal.timeout(15_000),
  });
  if (!response.ok) {
    throw new Error(`无法下载样式表: ${response.status}`);
  }
  return response.text();
}

function uniqueUrls(matches) {
  return [...new Set(matches.map((value) => value.replace(/&amp;/g, '&')))];
}

export async function localizeGoogleFontsCss(html) {
  const source = String(html);
  const importUrls = uniqueUrls([...source.matchAll(GOOGLE_FONTS_CSS_IMPORT_RE)].map((m) => m[1]));
  const linkUrls = uniqueUrls([...source.matchAll(GOOGLE_FONTS_LINK_RE)].map((m) => m[1]));
  const stylesheetUrls = uniqueUrls([...importUrls, ...linkUrls]);
  if (!stylesheetUrls.length) {
    return { html: source, localizedCount: 0, inlinedBytes: 0 };
  }

  const inlinedBlocks = [];
  for (const url of stylesheetUrls) {
    try {
      inlinedBlocks.push(`/* localized from ${url} */\n${await fetchStylesheet(url)}`);
    } catch {
      inlinedBlocks.push(`/* failed to localize ${url} */`);
    }
  }

  let next = source;
  for (const url of importUrls) {
    const pattern = new RegExp(
      `@import\\s+url\\(\\s*['"]?${url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"]?\\s*\\)\\s*;?`,
      'gi',
    );
    next = next.replace(pattern, '');
  }
  next = next.replace(GOOGLE_FONTS_LINK_RE, '');

  const styleBlock = `<style data-mindspace-local="google-fonts">\n${inlinedBlocks.join('\n\n')}\n</style>`;
  if (/<head[^>]*>/i.test(next)) {
    next = next.replace(/<head([^>]*)>/i, `<head$1>${styleBlock}`);
  } else if (/<html[^>]*>/i.test(next)) {
    next = next.replace(/<html([^>]*)>/i, `<html$1><head>${styleBlock}</head>`);
  } else {
    next = `${styleBlock}\n${next}`;
  }

  const inlinedBytes = Buffer.byteLength(inlinedBlocks.join('\n'));
  return { html: next, localizedCount: stylesheetUrls.length, inlinedBytes };
}
