#!/usr/bin/env node
/**
 * 从 src/resources/oneos-web-legacy 生成 ONE-OS Web 端原型与侧边栏菜单项。
 *
 * 用法：node scripts/sync-oneos-web-prototypes.mjs
 */
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, '..');
const legacyRoot = path.join(projectRoot, 'src/resources/oneos-web-legacy');
const prototypesRoot = path.join(projectRoot, 'src/prototypes');
const sidebarPath = path.join(projectRoot, '.axhub/make/sidebar-tree.json');

const PAGE_ID_RE = /^[a-z0-9-]+$/u;

const XLL_MODULES = [
  { slug: 'oneos-web-safety-training', title: '业务-司机安全培训', skipCodegen: true },
];

const MODULES = [
  { slug: 'oneos-web-workbench', title: '工作台', files: ['工作台.jsx'] },
  { slug: 'oneos-web-login', title: '登录', files: ['登录.jsx'] },
  { slug: 'oneos-web-vehicle-asset', title: '车辆管理', files: ['车辆管理.jsx', '车辆管理-查看.jsx'] },
  { slug: 'oneos-web-contract-template', title: '合同模板管理', files: ['合同模板管理.jsx'] },
  { slug: 'oneos-web-help-center', title: '帮助中心', dir: '帮助中心' },
  { slug: 'oneos-web-finance', title: '财务管理', dir: '财务管理', excludeDirs: ['文档'] },
  { slug: 'oneos-web-procurement', title: '采购管理', dir: '采购管理' },
  { slug: 'oneos-web-lease-contract', title: '车辆租赁合同', dir: '车辆租赁合同' },
  { slug: 'oneos-web-h2-station', title: '加氢站管理', dir: '加氢站管理', excludeDirs: ['export-tools', 'AI-加氢站站点信息-complete'] },
  { slug: 'oneos-web-data-analysis', title: '数据分析', dir: '数据分析' },
  { slug: 'oneos-web-ledger-data', title: '台账数据', dir: '台账数据', excludeDirs: ['docs'] },
  { slug: 'oneos-web-business', title: '业务管理', dir: '业务管理', excludeDirs: ['文档', 'export-tools', 'AI-保险采购-complete'] },
  { slug: 'oneos-web-ops', title: '运维管理', dir: '运维管理' },
  { slug: 'oneos-web-requirements', title: '需求说明', dir: '需求说明', docsOnly: true },
];

function slugifyPageId(relPath) {
  const stem = relPath.replace(/\.jsx$/u, '').replace(/[\\/]/g, '-');
  const ascii = stem.replace(/[^\x00-\x7F]/gu, (ch) => `u${ch.charCodeAt(0).toString(16)}`);
  let id = ascii.toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
  if (!id || !PAGE_ID_RE.test(id)) {
    id = `p${Math.abs(hashCode(relPath)).toString(36)}`;
  }
  return id.slice(0, 48);
}

function hashCode(value) {
  let hash = 0;
  for (let i = 0; i < value.length; i += 1) {
    hash = ((hash << 5) - hash) + value.charCodeAt(i);
    hash |= 0;
  }
  return hash;
}

function collectJsxFiles(module) {
  if (module.docsOnly) {
    return [];
  }
  if (module.files) {
    return module.files.map((file) => ({
      rel: file,
      abs: path.join(legacyRoot, file),
      title: file.replace(/\.jsx$/u, ''),
    }));
  }
  const baseDir = path.join(legacyRoot, module.dir);
  const results = [];
  const walk = (dir, prefix = '') => {
    if (!fs.existsSync(dir)) return;
    for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
      if (entry.name.startsWith('.')) continue;
      const full = path.join(dir, entry.name);
      const rel = path.posix.join(module.dir, prefix, entry.name).replace(/\\/g, '/');
      if (entry.isDirectory()) {
        if (module.excludeDirs?.includes(entry.name)) continue;
        walk(full, prefix ? `${prefix}/${entry.name}` : entry.name);
        continue;
      }
      if (!entry.name.endsWith('.jsx')) continue;
      results.push({
        rel,
        abs: full,
        title: entry.name.replace(/\.jsx$/u, ''),
      });
    }
  };
  walk(baseDir);
  return results.sort((a, b) => a.rel.localeCompare(b.rel, 'zh-CN'));
}

function prepareLegacyJsx(sourcePath, targetPath) {
  const raw = fs.readFileSync(sourcePath, 'utf8');
  let content = raw;
  if (!/export\s+default\s+Component/u.test(content)) {
    content = `${content.trim()}\n\nexport default Component;\n`;
  }
  fs.mkdirSync(path.dirname(targetPath), { recursive: true });
  fs.writeFileSync(targetPath, content, 'utf8');
}

function writeRequirementsPrototype(module) {
  const protoDir = path.join(prototypesRoot, module.slug);
  fs.mkdirSync(protoDir, { recursive: true });
  const indexTsx = `/**
 * @name ${module.title}
 * 自 ONE-OS web端/需求说明 归档
 */
import React, { useMemo, useState } from 'react';
import { Card, Col, Input, List, Row, Typography } from 'antd';

const DOC_MAP = import.meta.glob('../../resources/oneos-web-legacy/需求说明/**/*', {
  query: '?raw',
  import: 'default',
  eager: true,
});

const FILES = Object.keys(DOC_MAP)
  .map((key) => key.replace('../../resources/oneos-web-legacy/需求说明/', ''))
  .filter(Boolean)
  .sort((a, b) => a.localeCompare(b, 'zh-CN'))
  .map((rel) => ({ rel, title: rel }));

export default function OneosWebRequirementsPage() {
  const [query, setQuery] = useState('');
  const [active, setActive] = useState(FILES[0]?.rel ?? '');

  const filtered = useMemo(() => {
    const q = query.trim();
    if (!q) return FILES;
    return FILES.filter((item) => item.title.includes(q));
  }, [query]);

  const content = useMemo(() => {
    if (!active) return '';
    const key = \`../../resources/oneos-web-legacy/需求说明/\${active}\`;
    return String(DOC_MAP[key] ?? '无法加载文档');
  }, [active]);

  return (
    <Row gutter={16} style={{ padding: 16, minHeight: '100vh', background: '#f5f7fa' }}>
      <Col span={7}>
        <Card title="${module.title}" extra={<Input.Search allowClear placeholder="搜索文档" onSearch={setQuery} onChange={(e) => setQuery(e.target.value)} style={{ width: 160 }} />}>
          <List
            size="small"
            dataSource={filtered}
            renderItem={(item) => (
              <List.Item style={{ cursor: 'pointer', background: item.rel === active ? '#e8f3ff' : undefined }} onClick={() => setActive(item.rel)}>
                {item.title}
              </List.Item>
            )}
          />
        </Card>
      </Col>
      <Col span={17}>
        <Card>
          <Typography.Paragraph style={{ whiteSpace: 'pre-wrap', marginBottom: 0 }}>{content}</Typography.Paragraph>
        </Card>
      </Col>
    </Row>
  );
}
`;
  fs.writeFileSync(path.join(protoDir, 'index.tsx'), indexTsx, 'utf8');
}

function writePrototype(module, pages) {
  const protoDir = path.join(prototypesRoot, module.slug);
  const pagesDir = path.join(protoDir, 'pages');
  fs.mkdirSync(pagesDir, { recursive: true });

  const pageEntries = [];
  const importLines = [];
  const usedIds = new Set();

  pages.forEach((page, index) => {
    const fileName = `${String(index + 1).padStart(2, '0')}-${path.basename(page.rel)}`;
    const target = path.join(pagesDir, fileName);
    prepareLegacyJsx(page.abs, target);
    const importName = `Page${index + 1}`;
    importLines.push(`import ${importName} from './pages/${fileName}';`);
    let id = slugifyPageId(page.rel);
    while (usedIds.has(id)) id = `${id}-${index + 1}`;
    usedIds.add(id);
    pageEntries.push({ id, title: page.title, importName });
  });

  const pagesArray = pageEntries.map((p) => `    { id: '${p.id}', title: '${p.title.replace(/'/g, "\\'")}', component: ${p.importName} },`).join('\n');

  const indexTsx = `/**
 * @name ${module.title}
 * 自 ONE-OS web端 原稿复刻（${pages.length} 个页面）
 */
import '../../common/oneosWebLegacy/legacyGlobals';
import React from 'react';
${importLines.join('\n')}
import { OneosWebLegacyShell } from '../../common/oneosWebLegacy/OneosWebLegacyShell';

const pages = [
${pagesArray}
];

export default function ${toComponentName(module.slug)}() {
  return (
    <OneosWebLegacyShell
      moduleTitle="${module.title}"
      pages={pages}
      defaultPageId="${pageEntries[0]?.id ?? ''}"
    />
  );
}
`;
  fs.writeFileSync(path.join(protoDir, 'index.tsx'), indexTsx, 'utf8');
}

function toComponentName(slug) {
  return slug
    .split('-')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join('');
}

function toSidebarItem(module) {
  return {
    id: `item:prototypes:${module.slug}`,
    kind: 'item',
    title: module.title,
    itemKey: `prototypes/${module.slug}`,
  };
}

function updateSidebar(webModules, xllModules) {
  const sidebar = JSON.parse(fs.readFileSync(sidebarPath, 'utf8'));
  const prefix = 'item:prototypes:oneos-web-';
  const existing = (sidebar.prototypes ?? []).filter(
    (item) =>
      item.id !== 'folder-prototypes-oneos-web'
      && item.id !== 'folder-prototypes-xll-miniapp'
      && item.itemKey !== 'prototypes/contract-template-management'
      && !String(item.id).startsWith(prefix)
      && !String(item.itemKey).startsWith('prototypes/oneos-web-'),
  );

  const xllFolder = {
    id: 'folder-prototypes-xll-miniapp',
    kind: 'folder',
    title: '小羚羚小程序',
    children: xllModules.map(toSidebarItem),
  };

  const oneosFolder = {
    id: 'folder-prototypes-oneos-web',
    kind: 'folder',
    title: 'ONE-OS Web 端',
    defaultExpanded: true,
    children: webModules.map(toSidebarItem),
  };

  sidebar.prototypes = [...existing, xllFolder, oneosFolder];
  sidebar.updatedAt = new Date().toISOString();
  fs.writeFileSync(sidebarPath, `${JSON.stringify(sidebar, null, 2)}\n`, 'utf8');
}

function main() {
  if (!fs.existsSync(legacyRoot)) {
    console.error('缺少 src/resources/oneos-web-legacy，请先复制 ONE-OS web端 资料。');
    process.exit(1);
  }

  const allModules = [...XLL_MODULES, ...MODULES];

  for (const module of allModules) {
    if (module.skipCodegen) {
      console.log(`[skip codegen] ${module.slug}（入口由项目内手写维护）`);
      continue;
    }
    if (module.docsOnly) {
      writeRequirementsPrototype(module);
      console.log(`[ok] ${module.slug} (需求说明文档浏览)`);
      continue;
    }
    const pages = collectJsxFiles(module);
    if (!pages.length) {
      console.warn(`[skip] ${module.slug}: 未找到 jsx 页面`);
      continue;
    }
    writePrototype(module, pages);
    console.log(`[ok] ${module.slug} (${pages.length} pages)`);
  }

  updateSidebar(MODULES, XLL_MODULES);
  console.log('已更新 .axhub/make/sidebar-tree.json');
}

main();
