const { escapeHtml } = require('../utils/html');

/**
 * 将 CSS 文本安全嵌入到 <style> 中，避免出现 `</style>` 结束标签导致样式块被提前终止。
 * @param {string} cssText CSS 文本
 * @returns {string} 安全的 CSS 文本
 */
function makeCssSafeForHtmlStyleTag(cssText) {
  if (typeof cssText !== 'string') {
    return '';
  }

  return cssText.replace(/<\/style/gi, '<\\/style');
}

function normalizeFontWeight(input) {
  if (input === undefined || input === null) return 'normal';

  if (typeof input === 'number' && Number.isFinite(input)) {
    return String(input);
  }

  const raw = String(input).trim();
  if (!raw) return 'normal';

  if (/^(normal|bold|bolder|lighter)$/i.test(raw)) return raw.toLowerCase();
  if (/^[1-9]00$/.test(raw)) return raw;

  return raw;
}

function normalizeFontFamilyForCss(input) {
  const raw = String(input || '').trim();
  if (!raw) return '';

  const generics = new Set([
    'serif',
    'sans-serif',
    'monospace',
    'cursive',
    'fantasy',
    'system-ui',
    'ui-serif',
    'ui-sans-serif',
    'ui-monospace',
    'ui-rounded',
    'emoji',
    'math',
    'fangsong',
  ]);

  return raw
    .split(',')
    .map((part) => part.trim())
    .filter(Boolean)
    .map((part) => {
      const unquoted = part.replace(/^['"]|['"]$/g, '').trim();
      if (!unquoted) return '';
      if (generics.has(unquoted)) return unquoted;

      const needsQuotes = /\s/.test(unquoted);
      if (!needsQuotes) return unquoted;

      return `"${unquoted.replace(/"/g, '\\"')}"`;
    })
    .filter(Boolean)
    .join(', ');
}

function normalizeFontSource(input) {
  const raw = String(input || '')
    .trim()
    .toLowerCase();
  if (raw === 'css' || raw === 'google' || raw === 'system') return raw;
  return 'system';
}

function getNormalizedFontsConfig(config) {
  const fonts = config && config.fonts && typeof config.fonts === 'object' ? config.fonts : {};

  return {
    source: normalizeFontSource(fonts.source),
    family: normalizeFontFamilyForCss(fonts.family),
    weight: normalizeFontWeight(fonts.weight),
    cssUrl: String(fonts.cssUrl || fonts.href || '').trim(),
    preload: Boolean(fonts.preload),
  };
}

function tryGetUrlOrigin(input) {
  const raw = String(input || '').trim();
  if (!raw) return '';
  try {
    return new URL(raw).origin;
  } catch {
    return '';
  }
}

function buildStylesheetLinkTag(href, preload) {
  const safeHref = escapeHtml(href);
  if (!preload) return `<link rel="stylesheet" href="${safeHref}">`;

  return [
    `<link rel="preload" href="${safeHref}" as="style" onload="this.onload=null;this.rel='stylesheet'">`,
    `<noscript><link rel="stylesheet" href="${safeHref}"></noscript>`,
  ].join('\n');
}

// 生成字体相关 <link>
function generateFontLinks(config) {
  const fonts = getNormalizedFontsConfig(config);
  const links = [];

  // 全站基础字体：按配置加载
  if (fonts.source === 'css' && fonts.cssUrl) {
    const origin = tryGetUrlOrigin(fonts.cssUrl);
    if (origin) {
      links.push(`<link rel="preconnect" href="${escapeHtml(origin)}" crossorigin>`);
    }
    links.push(buildStylesheetLinkTag(fonts.cssUrl, fonts.preload));
  }

  if (fonts.source === 'google' && fonts.family) {
    links.push('<link rel="preconnect" href="https://fonts.googleapis.com">');
    links.push('<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>');

    const familyNoQuotes = fonts.family.replace(/[\"']/g, '').split(',')[0].trim();
    const weight = /^[1-9]00$/.test(fonts.weight) ? fonts.weight : '400';
    const familyParam = encodeURIComponent(familyNoQuotes).replace(/%20/g, '+');
    links.push(
      buildStylesheetLinkTag(
        `https://fonts.googleapis.com/css2?family=${familyParam}:wght@${weight}&display=swap`,
        fonts.preload
      )
    );
  }

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

// 生成字体 CSS 变量（单一字体配置）
function generateFontCss(config) {
  const fonts = getNormalizedFontsConfig(config);
  const family = fonts.family || 'system-ui, sans-serif';
  const weight = fonts.weight || 'normal';

  const css = `:root {\n  --font-body: ${family};\n  --font-weight-body: ${weight};\n}\n`;
  return makeCssSafeForHtmlStyleTag(css);
}

module.exports = {
  generateFontLinks,
  generateFontCss,
};
