import 'dotenv/config'
import fs from 'node:fs/promises';
import { URL } from 'node:url';
import { Transform } from 'node:stream';
import { Readable } from 'node:stream';
import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { createServer as createNodeServer } from 'node:http';
import process from 'node:process';
import { createAdaptorServer } from '@hono/node-server'  

// 创建 Hono 应用
const app = new Hono();

// 全局使用 Hono 日志中间件
app.use('*', logger());

// 常量定义
const isProduction = process.env.NODE_ENV === 'production';
const port = process.env.PORT || 8080;
const base = process.env.BASE || '/';
const ABORT_DELAY = 10000;

console.log('========================================');
console.log('开始初始化服务器...');
console.log(`环境: ${isProduction ? '生产环境' : '开发环境'}`);
console.log(`端口: ${port}`);
console.log(`基础路径: ${base}`);
console.log('========================================');

// 解析基础路径为 URL 对象
const baseUrl = new URL(base, `http://localhost:${port}`);
console.log(`基础URL解析完成: ${baseUrl.href}`);

// 创建服务器实例
console.log('正在创建服务器实例...');
const parentServer = createAdaptorServer({  
  fetch: app.fetch,  
  createServer: createNodeServer,  
  port: port,  
})
console.log('服务器实例创建成功');

// 生产环境中间件
let compressionMiddleware;
let sirvMiddleware;
if (isProduction) {
  console.log('生产环境: 加载压缩和静态文件中间件...');
  compressionMiddleware = (await import('compression')).default();
  sirvMiddleware = (await import('sirv')).default('./dist/client', { 
    extensions: [],
    baseUrl: base 
  });
  console.log('生产环境中间件加载完成');
}

// Vite 开发服务器
/** @type {import('vite').ViteDevServer | undefined} */
let vite;
if (!isProduction) {
  console.log('开发环境: 初始化 Vite 开发服务器...');
  const { createServer } = await import('vite');
  vite = await createServer({
    server: { 
      middlewareMode: {
        server: parentServer
      },
      hmr: {  
        port: 8081,
        clientPort: 443,
        path: 'vite-hmr'
      },
      proxy: {
        '/vite-hmr': {
          target: 'ws://localhost:8081',
          ws: true,
        },
      },
    },
    appType: 'custom',
    base,
  });
  console.log('Vite 开发服务器初始化完成');
}


// 开发环境模板处理函数 - 仅处理模板转换
const processDevTemplate = async (template) => {
  if (!isProduction && vite) {
    console.log('开发环境: 处理模板...');
    const processedTemplate = await vite.transformIndexHtml('/', template);
    console.log('开发环境模板处理完成');
    return processedTemplate;
  }
  return template;
};

// 生产环境模板处理函数 - 仅处理资源路径替换
const processProdTemplate = async (template) => {
  console.log('生产环境: 处理模板资源路径...');
  try {
    // 读取 manifest
    const manifestPath = new URL('./dist/client/.vite/manifest.json', import.meta.url);
    const manifestContent = await fs.readFile(manifestPath, 'utf-8');
    const manifest = JSON.parse(manifestContent);
    console.log('生产环境: 成功读取 manifest.json');

    // 获取 src/client/index.tsx 对应的资源信息
    const indexManifest = manifest['src/client/index.tsx'];
    if (!indexManifest) {
      throw new Error('manifest 中未找到 src/client/index.tsx 入口配置');
    }

    // 获取 src/style.css 对应的资源信息
    const styleManifest = manifest['src/style.css'];
    if (!styleManifest) {
      throw new Error('manifest 中未找到 src/style.css 入口配置');
    }

    const cssPath = new URL(styleManifest.file, baseUrl).pathname;
    const cssLinks = `<link href="${cssPath}" rel="stylesheet" />`;

    // 替换入口脚本
    const jsEntryPath = new URL(indexManifest.file, baseUrl).pathname;
    const entryScript = `<script type="module" src="${jsEntryPath}"></script>`;

    // 执行替换
    const processedTemplate = template
      .replace(/<link href="\/src\/style.css" rel="stylesheet"\/>/, cssLinks)
      .replace(/<script type="module" src="\/src\/client\/index.tsx"><\/script>/, entryScript);

    console.log('生产环境模板处理完成');
    return processedTemplate;

  } catch (err) {
    console.error('生产环境模板处理失败:', err);
    throw err;
  }
};

// SSR 渲染中间件函数
const createSsrHandler = (template, render, normalizedUrl) => {
  return async (c) => {
    let didError = false;
    let abortController;

    // 创建一个可读流用于 SSR 渲染内容
    const [htmlStart, htmlEnd] = template.split(`<!--app-html-->`);
    const ssrStream = new Readable({ read: () => {} });

    // 写入 HTML 头部
    ssrStream.push(htmlStart);

    // 设置响应头和状态码
    c.header('Content-Type', 'text/html');

    // 处理渲染
    const { pipe, abort } = render(normalizedUrl, {
      onShellError() {
        didError = true;
        c.status(500);
        ssrStream.push('<h1>服务器渲染出错</h1>');
        ssrStream.push(null); // 结束流
      },
      onShellReady() {
        console.log(`开始渲染页面: ${normalizedUrl}`);
        // 将渲染结果通过管道传入 ssrStream
        const transformStream = new Transform({
          transform(chunk, encoding, callback) {
            ssrStream.push(chunk, encoding);
            callback();
          }
        });

        pipe(transformStream);

        // 当 transformStream 完成时，添加 HTML 尾部
        transformStream.on('finish', () => {
          ssrStream.push(htmlEnd);
          ssrStream.push(null); // 结束流
          console.log(`页面渲染完成: ${normalizedUrl}`);
        });
      },
      onError(error) {
        didError = true;
        console.error('渲染过程出错:', error);
      },
    });

    // 设置超时中止
    abortController = new AbortController();
    const abortTimeout = setTimeout(() => {
      console.log(`渲染超时，终止请求: ${normalizedUrl}`);
      abort();
      abortController.abort();
    }, ABORT_DELAY);

    // 将流通过 Hono 响应返回
    return c.body(ssrStream, {
      onEnd: () => {
        clearTimeout(abortTimeout);
      }
    });
  };
};

// 统一的请求处理中间件 - 合并 API 和 SSR 渲染逻辑
app.use(async (c) => {
  try {
    // 使用 c.env 获取原生请求响应对象
    const req = c.env.incoming;
    const res = c.env.outgoing;
    const url = new URL(req.url, `http://${req.headers.host}`);
    const path = url.pathname;

    // 检查是否匹配基础路径
    if (!path.startsWith(baseUrl.pathname)) {
      return c.text('未找到', 404);
    }

    // 处理基础路径
    const normalizedUrl = path.replace(baseUrl.pathname, '/') || '/';
    console.log(`处理请求: ${normalizedUrl}`);

    // 开发环境：使用 Vite 中间件
    if (!isProduction && vite) {
      // 使用 Vite 中间件处理请求
      const handled = await new Promise((resolve) => {
        vite.middlewares(req, res, () => resolve(false));
      });
      
      // 如果 Vite 中间件已经处理了请求，直接返回
      if (handled) {
        return c.body;
      }


      // 动态加载最新 API 模块
      const apiModule = await vite.ssrLoadModule('./src/server/index.tsx');
      
      // 创建临时子应用并挂载路由
      const apiApp = new Hono();
      apiApp.route('/', apiModule.api);
      
      // 处理开发环境模板
      const template = await processDevTemplate(apiModule.template);
      apiApp.get('*', createSsrHandler(template, apiModule.render, normalizedUrl));

      // 直接由子应用处理 API 请求
      return apiApp.fetch(c.req.raw, {
        ...c.env,
        // 传递原始请求对象
        incoming: c.env.incoming,
        outgoing: c.env.outgoing
      });
    }
    // 生产环境：使用 compression 和 sirv 中间件
    else if (isProduction) {
      // 先尝试 compression 中间件
      const compressed = await new Promise((resolve) => {
        compressionMiddleware(req, res, () => resolve(false));
      });
      
      if (compressed) {
        return c.body;
      }
      
      // 再尝试 sirv 中间件处理静态文件
      const served = await new Promise((resolve) => {
        sirvMiddleware(req, res, () => resolve(false));
      });
      
      if (served) {
        return c.body;
      }

      // 生产环境：使用缓存的 API 路由
      const { api, template: rawTemplate, render } = (await import('./dist/server/index.js'));
      const apiApp = new Hono();
      apiApp.route('/', api);

      // 处理生产环境模板
      const template = await processProdTemplate(rawTemplate);
      apiApp.get('*', createSsrHandler(template, render, normalizedUrl));

      return apiApp.fetch(c.req.raw, {
        ...c.env,
        incoming: c.env.incoming,
        outgoing: c.env.outgoing
      });
    }

  } catch (e) {
    if (!isProduction && vite) {
      vite.ssrFixStacktrace(e);
      console.error('请求处理错误:', e.stack);
      return c.text(e.stack, 500);
    }
    console.error('请求处理错误:', e.stack);
    return c.text('服务器内部错误' + e.stack, 500);
  }
});

// 移除生产环境的 API 路由预加载（已在统一中间件中处理）
// 移除动态 API 路由中间件（已合并到统一中间件中）

// 启动服务器
console.log('准备启动服务器...');
parentServer.listen(port, () => {  
  console.log('========================================');
  console.log(`服务器已成功启动!`);
  console.log(`访问地址: http://localhost:${port}`);
  console.log(`环境: ${isProduction ? '生产环境' : '开发环境'}`);
  console.log('========================================');
})

// 统一的服务器关闭处理函数
const shutdownServer = async () => {
  console.log('正在关闭服务器...');
  
  // 1. 先关闭 Vite 开发服务器（包括 HMR 服务）
  if (!isProduction && vite) {
    console.log('正在关闭 Vite 开发服务器（包括 HMR 服务）...');
    try {
      await vite.close();
      console.log('Vite 开发服务器已关闭');
    } catch (err) {
      console.error('关闭 Vite 服务器时出错:', err);
    }
  }
  
  // 2. 关闭主服务器
  parentServer.close((err) => {
    if (err) {
      console.error('关闭主服务器时出错:', err);
      process.exit(1);
    }
    console.log('主服务器已关闭');
    process.exit(0);
  });
};

// 处理进程终止信号
process.on('SIGINT', shutdownServer);
process.on('SIGTERM', shutdownServer);