#!/usr/bin/env node
/**
 * 自动扫描 src/icons 下的 Fill、Linear、Multicolor 目录，
 * 生成包含所有静态 require() 的 src/icons/index.ts 文件。
 *
 * 用法：node scripts/generate-icons.js
 * 或：  yarn generate:icons
 */

const fs = require('fs');
const path = require('path');

const ICONS_DIR = path.resolve(__dirname, '../src/icons');
const OUTPUT_FILE = path.join(ICONS_DIR, 'index.ts');
const PREVIEW_FILE = path.join(ICONS_DIR, 'preview.html');
const CATEGORIES = ['Fill', 'Linear', 'Multicolor', 'Note', 'actionSheet', 'Logo', 'Avatar', 'GroupAvatar', 'Cartoon', 'Comp', 'Lottie'];
const CATEGORIES_DESC = {
  Fill: '通用填充类图标',
  Linear: '通用线性类图标',
  Multicolor: '通用多色类图标',
  Logo: 'Logo 相关图标',
  Note: '笔记图标',
  actionSheet: '操作面板图标',
  Cartoon: '卡通形象',
  Lottie: 'Lottie 动画(JSON)',
  Avatar: '预置用户头像',
  GroupAvatar: '预置群组头像',
  Comp: '',
};
const IMAGE_EXT = ['.png', '.jpg', '.jpeg', '.gif', '.webp'];
const LOTTIE_EXT = ['.json'];

const toKey = (filename) => {
  const name = path.basename(filename, path.extname(filename));
  // 将连字符/下划线转为驼峰，如 my-icon → myIcon
  return name.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
};

const scanCategory = (category) => {
  const dir = path.join(ICONS_DIR, category);
  if (!fs.existsSync(dir)) return {};
  const allowExt = category === 'Lottie' ? LOTTIE_EXT : IMAGE_EXT;
  return fs
    .readdirSync(dir)
    .filter((f) => allowExt.includes(path.extname(f).toLowerCase()))
    .sort()
    .reduce((acc, file) => {
      acc[toKey(file)] = `./${category}/${file}`;
      return acc;
    }, {});
};

const escapeHtml = (text) => {
  return String(text)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
};

const scanPreviewGroups = () => {
  if (!fs.existsSync(ICONS_DIR)) return [];

  return CATEGORIES.map((group) => {
      const dir = path.join(ICONS_DIR, group);
      if (!fs.existsSync(dir)) return { group, desc: CATEGORIES_DESC[group] || '', items: [] };
      const allowExt = group === 'Lottie' ? LOTTIE_EXT : IMAGE_EXT;
      const items = fs
        .readdirSync(dir)
        .filter((file) => allowExt.includes(path.extname(file).toLowerCase()))
        .sort()
        .map((file) => {
          const key = toKey(file);
          const isLottie = group === 'Lottie';
          return {
            file,
            key,
            ref: `Icons.${group}.${key}`,
            relPath: `./${group}/${file}`,
            kind: (() => {
              if (isLottie) return 'lottie';
              if (group === 'GroupAvatar' || group === 'Avatar' || group === 'Cartoon' || group === 'Comp' || group === 'Logo') return 'large-image'
              return 'image';
            })(),
          };
        });
      return { group, desc: CATEGORIES_DESC[group] || '', items };
    })
    .filter(({ items }) => items.length > 0);
};

const buildPreviewHtml = (groups) => {
  const sections = groups
    .map(({ group, desc, items }) => {
      const cards = items
        .map(
          (item) => `
        <button class="icon-card" data-copy="${escapeHtml(item.ref)}" title="点击复制 ${escapeHtml(item.ref)}">
          ${(() => {
            switch (item.kind) {
              case 'lottie':
                return `<div class="lottie-preview" data-lottie-src="${escapeHtml(item.relPath)}">Lottie</div>`;
              case 'large-image':
                  return `<img class="large-image" src="${escapeHtml(item.relPath)}" alt="${escapeHtml(item.key)}" loading="lazy" />`;
              case 'image':
                return `<img class="icon-image" src="${escapeHtml(item.relPath)}" alt="${escapeHtml(item.key)}" loading="lazy" />`;
            }
          })()}
          <div class="icon-key">${escapeHtml(item.key)}</div>
          <div class="icon-file">${escapeHtml(item.file)}</div>
        </button>`,
        )
        .join('\n');

      return `
    <section class="group">
      <div class="group-header">
        <h2>${escapeHtml(group)}</h2>
        ${desc ? `<em>${escapeHtml(desc)}</em>` : ''}
        <span>${items.length} icons</span>
      </div>
      <div class="grid">
${cards}
      </div>
    </section>`;
    })
    .join('\n');

  return `<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Icons Preview</title>
  <style>
    :root {
      --bg: #171b22;
      --text: #f2f4f8;
      --muted: #b5bdcd;
      --muted-2: #a0a8b8;
      --card-bg: rgba(42, 49, 61, 0.18);
      --card-hover-bg: rgba(42, 49, 61, 0.94);
      --card-border: #424a58;
      --card-hover-border: #5a6679;
      --card-shadow: 0 8px 16px rgba(0,0,0,.25);
      --key-color: #f2f4f8;
      --ref-color: #8bb2ff;
      --file-color: #a4acbc;
      --btn-bg: #2a313d;
      --btn-border: #525d72;
      --btn-text: #f2f4f8;
      color-scheme: dark;
    }
    html[data-theme='light'] {
      --bg: #f5f6f8;
      --text: #1f2329;
      --muted: #5c6470;
      --muted-2: #7a8190;
      --card-bg: rgba(255, 255, 255, 0.92);
      --card-hover-bg: rgba(255, 255, 255, 1);
      --card-border: #e7eaf0;
      --card-hover-border: #cfd7e6;
      --card-shadow: 0 6px 16px rgba(0,0,0,.08);
      --key-color: #1f2329;
      --ref-color: #2b6cff;
      --file-color: #7a8190;
      --btn-bg: #ffffff;
      --btn-border: #d9dfea;
      --btn-text: #1f2329;
      color-scheme: light;
    }
    body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); }
    .wrap { padding: 24px; max-width: 1440px; margin: 0 auto; }
    .header { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 8px; }
    .title { margin: 0 0 8px; font-size: 24px; }
    .desc { margin: 0 0 20px; color: var(--muted); font-size: 14px; }
    .theme-toggle {
      border: 1px solid var(--btn-border); background: var(--btn-bg); color: var(--btn-text); border-radius: 10px;
      padding: 8px 12px; cursor: pointer; font-size: 13px;
    }
    .group { margin-bottom: 28px; }
    .group-header { display: flex; align-items: baseline; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
    .group-header h2 { margin: 0; font-size: 18px; }
    .group-header em { color: var(--muted-2); font-style: normal; font-size: 12px; }
    .group-header span { color: var(--muted); font-size: 13px; }
    .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
    .icon-card {
      border: 1px solid var(--card-border); border-radius: 12px; background: var(--card-bg); padding: 12px; text-align: left; cursor: pointer;
      display: flex; flex-direction: column; gap: 6px; transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
    }
    .icon-card:hover { transform: translateY(-1px); background: var(--card-hover-bg); box-shadow: var(--card-shadow); border-color: var(--card-hover-border); }
    .icon-image { width: 28px; height: 28px; object-fit: contain; }
    .large-image { width: 96px; height: 72px; object-fit: contain; }
    .lottie-preview {
      width: 96px; height: 72px;
      display: flex; align-items: center; justify-content: center; color: var(--muted-2); font-size: 10px; letter-spacing: .3px;
      overflow: hidden;
    }
    .icon-key { font-size: 14px; font-weight: 600; color: var(--key-color); word-break: break-all; }
    .icon-ref { font-size: 12px; color: var(--ref-color); word-break: break-all; }
    .icon-file { font-size: 12px; color: var(--file-color); word-break: break-all; }
    .toast {
      position: fixed; right: 16px; bottom: 16px; padding: 10px 12px; border-radius: 8px; background: #111827; color: #fff;
      opacity: 0; transform: translateY(6px); transition: all .18s ease; pointer-events: none; font-size: 13px;
    }
    .toast.show { opacity: 1; transform: translateY(0); }
  </style>
</head>
<body>
  <div class="wrap">
    <div class="header">
      <h1 class="title">智在记录 - Icons Preview</h1>
      <button id="themeToggle" class="theme-toggle" type="button">切换暗色</button>
    </div>
    <p class="desc">按目录分组展示，点击卡片复制图标引用</p>
${sections}
  </div>
  <div id="toast" class="toast"></div>
  <script>
    const htmlEl = document.documentElement;
    const themeToggleEl = document.getElementById('themeToggle');
    const updateThemeButtonText = () => {
      const isDark = htmlEl.getAttribute('data-theme') === 'dark';
      themeToggleEl.textContent = isDark ? '切换亮色' : '切换暗色';
    };
    const initTheme = () => {
      htmlEl.setAttribute('data-theme', 'dark');
      updateThemeButtonText();
    };
    themeToggleEl.addEventListener('click', () => {
      const nextTheme = htmlEl.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
      htmlEl.setAttribute('data-theme', nextTheme);
      updateThemeButtonText();
    });
    initTheme();

    const toastEl = document.getElementById('toast');
    const showToast = (text) => {
      toastEl.textContent = text;
      toastEl.classList.add('show');
      clearTimeout(showToast._timer);
      showToast._timer = setTimeout(() => toastEl.classList.remove('show'), 1200);
    };

    const copyText = async (text) => {
      try {
        await navigator.clipboard.writeText(text);
        showToast('已复制: ' + text);
      } catch (e) {
        const input = document.createElement('textarea');
        input.value = text;
        document.body.appendChild(input);
        input.select();
        document.execCommand('copy');
        document.body.removeChild(input);
        showToast('已复制: ' + text);
      }
    };

    document.querySelectorAll('.icon-card').forEach((card) => {
      card.addEventListener('click', () => copyText(card.getAttribute('data-copy') || ''));
    });

    const initLottiePreview = () => {
      const lottieHolders = Array.from(document.querySelectorAll('.lottie-preview[data-lottie-src]'));
      if (!lottieHolders.length) return;

      const script = document.createElement('script');
      script.src = 'https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js';
      script.async = true;
      script.onload = () => {
        if (!window.lottie) return;
        lottieHolders.forEach((holder) => {
          const src = holder.getAttribute('data-lottie-src');
          if (!src) return;
          holder.textContent = '';
          const animation = window.lottie.loadAnimation({
            container: holder,
            renderer: 'svg',
            loop: true,
            autoplay: false,
            path: src,
          });
          animation.goToAndStop(0, true);
          const cardEl = holder.closest('.icon-card');
          if (cardEl) {
            cardEl.addEventListener('mouseenter', () => animation.play());
            cardEl.addEventListener('mouseleave', () => {
              animation.stop();
              animation.goToAndStop(0, true);
            });
          }
        });
      };
      script.onerror = () => {
        // CDN 加载失败时保持占位文本
      };
      document.head.appendChild(script);
    };

    initLottiePreview();
  </script>
</body>
</html>
`;
};

const buildCategoryBlock = (category, entries) => {
  const lines = Object.entries(entries).map(
    ([key, relPath]) => `    ${key}: require('${relPath}'),`,
  );
  return [`  ${category}: {`, ...lines, '  },'].join('\n');
};

const generate = () => {
  const allCategories = CATEGORIES.map((cat) => ({
    name: cat,
    entries: scanCategory(cat),
  }));

  // 生成类型定义
  const categoryTypeLines = allCategories.map(({ name, entries }) => {
    // const valueType = name === 'Lottie' ? 'number' : 'ImageSourcePropType';
    const valueType = 'number';
    const keyLines = Object.keys(entries)
      .map((k) => `    ${k}: ${valueType};`)
      .join('\n');
    return `  ${name}: {\n${keyLines}\n  };`;
  });

  // 生成 Icons 对象内容
  const categoryBlocks = allCategories.map(({ name, entries }) =>
    buildCategoryBlock(name, entries),
  );

  const lines = [
    '// This file is auto-generated. Do not edit manually.',
    '// Run `yarn generate:icons` to regenerate.',
    '',
    // "import { ImageSourcePropType } from 'react-native';",
    '',
    'type IconsType = {',
    ...categoryTypeLines,
    '};',
    '',
    'export const Icons: IconsType = {',
    ...categoryBlocks,
    '};',
    '',
  ];

  fs.writeFileSync(OUTPUT_FILE, lines.join('\n'), 'utf8');
  const previewGroups = scanPreviewGroups();
  fs.writeFileSync(PREVIEW_FILE, buildPreviewHtml(previewGroups), 'utf8');

  const total = allCategories.reduce((n, { entries }) => n + Object.keys(entries).length, 0);
  console.log(`✅ icons/index.ts generated — ${total} icons across ${CATEGORIES.length} categories`);
  console.log(`✅ icons/preview.html generated — ${previewGroups.reduce((n, g) => n + g.items.length, 0)} icons`);
  allCategories.forEach(({ name, entries }) => {
    console.log(`   ${name}: ${Object.keys(entries).join(', ') || '(empty)'}`);
  });
};

generate();
