import { defineConfig } from 'vite';
import type { Plugin } from 'vite';
import fs from 'fs';
import path from 'path';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

// ── 构建模式也需要的插件（静态导入） ──
import { addAxhubMarker } from './vite-plugins/addAxhubMarker';
import { axhubComponentEnforcer } from './vite-plugins/axhubComponentEnforcer';
import { forceInlineDynamicImportsOff } from './vite-plugins/forceInlineDynamicImportsOff';
import { injectStablePageIds } from './vite-plugins/injectStablePageIds';
import {
  MAKE_CONFIG_RELATIVE_PATH,
  MAKE_ENTRIES_RELATIVE_PATH,
} from './vite-plugins/utils/makeConstants';
import { readEntriesManifest, scanProjectEntries, writeEntriesManifestAtomic } from './vite-plugins/utils/entriesManifest';

// ── 仅 dev server 模式需要的插件 ──
// 使用动态 import() 避免在 build 模式下加载这些模块。
// lowdbService 等单例会在模块求值时创建持久资源，导致 vite build 进程无法退出。
async function loadServePlugins(): Promise<Plugin[]> {
  const [
    { aiCliPlugin },
    { autoDebugPlugin },
    { axureBridgeProxyPlugin },
    { canvasApiPlugin },
    { ccConnectApiPlugin },
    { codeReviewPlugin },
    { configApiPlugin },
    { dataManagementApiPlugin },
    { docsApiPlugin },
    { docsImportApiPlugin },
    { downloadDistPlugin },
    { exportHtmlApiPlugin },
    { exportImageProxyPlugin },
    { fileSystemApiPlugin },
    { gitVersionApiPlugin },
    { lanAccessControlPlugin },
    { mediaManagementApiPlugin },
    { serveAdminPlugin },
    { sourceApiPlugin },
    { specDocApiPlugin },
    { subPagesApiPlugin },
    { templatesApiPlugin },
    { themesApiPlugin },
    { unsetReferenceApiPlugin },
    { uploadDocsApiPlugin },
    { versionApiPlugin },
    { virtualHtmlPlugin },
    { websocketPlugin },
    { writeDevServerInfoPlugin },
  ] = await Promise.all([
    import('./vite-plugins/aiCliPlugin'),
    import('./vite-plugins/autoDebugPlugin'),
    import('./vite-plugins/axureBridgeProxyPlugin'),
    import('./vite-plugins/canvasApiPlugin'),
    import('./vite-plugins/ccConnectApiPlugin'),
    import('./vite-plugins/codeReviewPlugin'),
    import('./vite-plugins/configApiPlugin'),
    import('./vite-plugins/dataManagementApiPlugin'),
    import('./vite-plugins/docsApiPlugin'),
    import('./vite-plugins/docsImportApiPlugin'),
    import('./vite-plugins/downloadDistPlugin'),
    import('./vite-plugins/exportHtmlApiPlugin'),
    import('./vite-plugins/exportImageProxyPlugin'),
    import('./vite-plugins/fileSystemApiPlugin'),
    import('./vite-plugins/gitVersionApiPlugin'),
    import('./vite-plugins/lanAccessControlPlugin'),
    import('./vite-plugins/mediaManagementApiPlugin'),
    import('./vite-plugins/serveAdminPlugin'),
    import('./vite-plugins/sourceApiPlugin'),
    import('./vite-plugins/specDocApiPlugin'),
    import('./vite-plugins/subPagesApiPlugin'),
    import('./vite-plugins/templatesApiPlugin'),
    import('./vite-plugins/themesApiPlugin'),
    import('./vite-plugins/unsetReferenceApiPlugin'),
    import('./vite-plugins/uploadDocsApiPlugin'),
    import('./vite-plugins/versionApiPlugin'),
    import('./vite-plugins/virtualHtml'),
    import('./vite-plugins/websocketPlugin'),
    import('./vite-plugins/writeDevServerInfoPlugin'),
  ]);

  return [
    lanAccessControlPlugin(),
    writeDevServerInfoPlugin(),
    serveAdminPlugin(),
    axureBridgeProxyPlugin(),
    exportImageProxyPlugin(),
    virtualHtmlPlugin(),
    websocketPlugin(),
    versionApiPlugin(),
    downloadDistPlugin(),
    exportHtmlApiPlugin(),
    docsImportApiPlugin(),
    docsApiPlugin(),
    canvasApiPlugin(),
    templatesApiPlugin(),
    uploadDocsApiPlugin(),
    sourceApiPlugin(),
    specDocApiPlugin(),
    subPagesApiPlugin(),
    unsetReferenceApiPlugin(),
    themesApiPlugin(),
    fileSystemApiPlugin(),
    dataManagementApiPlugin(),
    mediaManagementApiPlugin(),
    codeReviewPlugin(),
    autoDebugPlugin(),
    configApiPlugin(),
    aiCliPlugin(),
    gitVersionApiPlugin(),
    ccConnectApiPlugin(),
  ];
}

const projectRoot = process.cwd();
const configPath = path.resolve(projectRoot, MAKE_CONFIG_RELATIVE_PATH);
let axhubConfig: any = { server: { host: 'localhost', allowLAN: true } };
if (fs.existsSync(configPath)) {
  try {
    axhubConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
  } catch (error) {
    console.warn(`Failed to parse ${MAKE_CONFIG_RELATIVE_PATH}, using defaults:`, error);
  }
}

writeEntriesManifestAtomic(
  projectRoot,
  scanProjectEntries(projectRoot, ['components', 'prototypes', 'themes']),
);
const entries = readEntriesManifest(projectRoot);

const entryKey = process.env.ENTRY_KEY;
const jsEntries = entries.js as Record<string, string>;
const htmlEntries = entries.html as Record<string, string>;

const hasSingleEntry = typeof entryKey === 'string' && entryKey.length > 0;
let rollupInput: Record<string, string> = htmlEntries;

if (hasSingleEntry) {
  if (!jsEntries[entryKey as string]) {
    throw new Error(`ENTRY_KEY=${entryKey} 未在 ${MAKE_ENTRIES_RELATIVE_PATH} 中找到对应入口文件。请确保目录 src/${entryKey} 存在且包含 index.tsx 文件。`);
  }
  rollupInput = { [entryKey as string]: jsEntries[entryKey as string] };
}

const isIifeBuild = hasSingleEntry;

export default defineConfig(async ({ command }) => {
  const isServe = command === 'serve';

  // 仅在 serve 模式才加载 server-only 插件，避免 build 进程被持久资源阻塞
  const servePlugins = isServe ? await loadServePlugins() : [];

  const config: any = {
    plugins: [
      tailwindcss(),
      injectStablePageIds(),
      ...servePlugins,
      forceInlineDynamicImportsOff(isIifeBuild),
      react({
        jsxRuntime: 'classic',
        babel: { configFile: false, babelrc: false }
      }),
      isIifeBuild ? addAxhubMarker() : null,
      isIifeBuild ? axhubComponentEnforcer(jsEntries[entryKey as string]) : null
    ].filter(Boolean) as Plugin[],

    root: 'src',

    optimizeDeps: {
      // React Fast Refresh 在开发态会接管 react/react-dom 的依赖预处理。
      // 这里不要再把它们排除掉，否则会和 plugin-react 的 include 冲突。
      exclude: [],
      include: [
        'lucide-react'
      ]
    },

    resolve: {
      alias: [
        { find: '@', replacement: path.resolve(projectRoot, 'src') },
        !isIifeBuild && !isServe && {
          find: /^react$/,
          replacement: path.resolve(projectRoot, 'src/common/react-shim.js')
        },
        !isIifeBuild && !isServe && {
          find: /^react-dom$/,
          replacement: path.resolve(projectRoot, 'src/common/react-dom-shim.js')
        },
        !isIifeBuild && !isServe && {
          find: /^react\/.*/,
          replacement: path.resolve(projectRoot, 'src/common/react-shim.js')
        },
        !isIifeBuild && !isServe && {
          find: /^react-dom\/.*/,
          replacement: path.resolve(projectRoot, 'src/common/react-dom-shim.js')
        }
      ].filter(Boolean) as { find: string | RegExp; replacement: string }[]
    },

    server: {
      port: 51720, // 默认从 51720 开始，如果被占用会自动尝试 51721, 51722...
      strictPort: false, // 端口被占用时自动尝试下一个端口
      host: '0.0.0.0', // 统一使用 0.0.0.0 绑定，确保端口检测正确
      open: false, // 开发态不要自动打开浏览器，避免端口回退时误打开 51721/51722 等页面
      cors: true,
      // HMR 配置
      hmr: {
        // 禁用 Vite 的错误覆盖层（Error Overlay）
        // 原因：项目使用多入口架构（prototypes、components 等），Vite 的 Error Overlay 会在所有打开的页面上显示错误
        // 这导致用户在访问页面 A 时，如果页面 B 出现构建错误，错误会跨页面显示在页面 A 上，造成困扰
        // 解决方案：禁用 Vite 的 Error Overlay，使用 dev-template.html 中已实现的自定义错误捕获和显示系统
        // 优点：避免跨页面错误显示，保持错误提示的页面隔离性，风险最小
        overlay: false
      },
      headers: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization'
      }
    },

    build: {
      outDir: path.resolve(projectRoot, 'dist'),
      emptyOutDir: !isIifeBuild,
      target: isIifeBuild ? 'es2015' : 'esnext',
      assetsInlineLimit: 1024 * 1024, // 1MB - 小于此大小的图片会被内联为 Base64

      rollupOptions: {
        input: rollupInput,

        external: isIifeBuild ? ['react', 'react-dom'] : [],

        output: {
          entryFileNames: (chunkInfo: { name: string }) => `${chunkInfo.name}.js`,
          format: isIifeBuild ? 'iife' : 'es',
          name: 'UserComponent',

          ...(isIifeBuild
            ? {
              globals: {
                react: 'React',
                'react-dom': 'ReactDOM'
              },
              generatedCode: { constBindings: false }
            }
            : {})
        }
      },

      minify: isIifeBuild ? 'esbuild' : false
    },

    esbuild: isIifeBuild
      ? {
        target: 'es2015',
        legalComments: 'none',
        keepNames: true
      }
      : {
        jsx: 'transform',
        jsxFactory: 'React.createElement',
        jsxFragment: 'React.Fragment'
      },

    test: {
      globals: true,
      environment: 'node',
      include: [
        'tests/**/*.test.ts',
        'tests/**/*.test.tsx',
        'vite-plugins/**/*.test.ts',
      ],
      root: '.',
    }
  };

  return config;
});
