// 必须第一个导入：修复 monorepo 下 cool-admin 路径探测问题
import './monorepo-fix';
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as orm from '@midwayjs/typeorm';
import {
  Configuration,
  App,
  IMidwayApplication,
  Inject,
  ILogger,
  MidwayWebRouterService,
} from '@midwayjs/core';
import * as koa from '@midwayjs/koa';
import * as crossDomain from '@midwayjs/cross-domain';
import * as validate from '@midwayjs/validate';
import * as info from '@midwayjs/info';
import * as staticFile from '@midwayjs/static-file';
import * as cron from '@midwayjs/cron';
import * as DefaultConfig from './config/config.default';
import * as LocalConfig from './config/config.local';
import * as ProdConfig from './config/config.prod';
import * as cool from '@cool-midway/core';
import * as upload from '@midwayjs/upload';
import * as socketio from '@midwayjs/socketio';
import { NetaClawAgentChannelService } from './modules/netaclaw/service/agent_channel';
import { DesktopOpConfigBootstrap } from './modules/desktop_op/service/desktop_op_config_bootstrap.js';
import { acquireRuntimeLock, releaseRuntimeLock } from './comm/runtime-lock';
import { openBrowser } from './comm/browser';
import { pDataPath } from './comm/path';
import { registerGracefulShutdown, triggerGracefulShutdown } from './comm/graceful-shutdown';
import { writeRuntimeInfo, clearRuntimeInfo } from './comm/runtime-info';
import { ensureDpiAware } from './modules/desktop_op/runtime/dpi.js';
// import * as task from '@cool-midway/task';
// import * as rpc from '@cool-midway/rpc';

@Configuration({
  imports: [
    // https://koajs.com/
    koa,
    // 是否开启跨域(注：顺序不能乱放！！！) http://www.midwayjs.org/docs/extensions/cross_domain
    crossDomain,
    // 静态文件托管 https://midwayjs.org/docs/extensions/static_file
    staticFile,
    // orm https://midwayjs.org/docs/extensions/orm
    orm,
    // 参数验证 https://midwayjs.org/docs/extensions/validate
    validate,
    // 本地任务 http://www.midwayjs.org/docs/extensions/cron
    cron,
    // 文件上传
    upload,
    // cool-admin 官方组件 https://cool-js.com
    cool,
    // rpc 微服务 远程调用
    // rpc,
    // 任务与队列
    // task,
    // socketio，https://midwayjs.org/docs/extensions/socketio
    socketio,
    {
      component: info,
      enabledEnvironment: ['local', 'prod'],
    },
  ],
  importConfigs: [
    {
      default: DefaultConfig,
      local: LocalConfig,
      prod: ProdConfig,
    },
  ],
})
export class MainConfiguration {
  @App()
  app: IMidwayApplication;

  @Inject()
  webRouterService: MidwayWebRouterService;

  @Inject()
  logger: ILogger;

  async onReady() {
    // 设置 DPI 感知，确保 Windows 高 DPI 环境下坐标计算正确
    ensureDpiAware();

    const dataDir = pDataPath();
    const lockPath = path.join(dataDir, 'gpu-guard.lock');
    const runtimeInfoPath = path.join(dataDir, 'runtime-info.json');
    const configDir = path.dirname(process.env.GPU_GUARD_CONFIG_PATH || process.execPath);
    const port = this.app.getConfig('koa.port');
    const startedAt = new Date().toISOString();

    (global as any).__GPU_GUARD_RUNTIME_STARTED_AT__ = startedAt;
    (global as any).__GPU_GUARD_RUNTIME_READY__ = false;

    acquireRuntimeLock(lockPath);
    process.on('exit', () => releaseRuntimeLock(lockPath));

    registerGracefulShutdown(async () => {
      (global as any).__GPU_GUARD_RUNTIME_READY__ = false;
      clearRuntimeInfo(runtimeInfoPath);
      releaseRuntimeLock(lockPath);
      setTimeout(() => process.exit(0), 50);
    });

    process.on('SIGINT', () => {
      void triggerGracefulShutdown();
    });
    process.on('SIGTERM', () => {
      void triggerGracefulShutdown();
    });

    const channelService = await this.app
      .getApplicationContext()
      .getAsync(NetaClawAgentChannelService);
    await channelService.restoreConnectedRunners();

    const desktopOpBootstrap = await this.app
      .getApplicationContext()
      .getAsync(DesktopOpConfigBootstrap);
    await desktopOpBootstrap.ensureConfigAndLoad();

    (global as any).__GPU_GUARD_RUNTIME_READY__ = true;
    writeRuntimeInfo(runtimeInfoPath, {
      pid: process.pid,
      ready: true,
      startedAt,
      port,
      url: `http://127.0.0.1:${port}`,
      controlBaseUrl: `http://127.0.0.1:${port}/app/base/runtime`,
      controlSecret: process.env.NETA_TRAY_SECRET || '',
      dataDir,
      logDir: path.join(dataDir, 'logs'),
      configDir,
    });

    const autoOpenBrowser = this.app.getConfig('autoOpenBrowser');
    if ((process as any).pkg && autoOpenBrowser) {
      openBrowser(`http://127.0.0.1:${port}`);
    }

    // 确保 skills 目录存在
    const skillsDir = path.join(dataDir, 'skills');
    if (!fs.existsSync(skillsDir)) {
      fs.mkdirSync(skillsDir, { recursive: true });
    }
    const bundledSkillsDir = path.join(configDir, 'skills');
    if (fs.existsSync(bundledSkillsDir)) {
      for (const entry of fs.readdirSync(bundledSkillsDir, { withFileTypes: true })) {
        if (!entry.isDirectory()) continue;
        const sourceDir = path.join(bundledSkillsDir, entry.name);
        const targetDir = path.join(skillsDir, entry.name);
        if (!fs.existsSync(targetDir)) {
          fs.cpSync(sourceDir, targetDir, { recursive: true });
        }
      }
    }

    // SPA history fallback：非 API/静态资源的浏览器导航直接返回 index.html
    if ((process as any).pkg) {
      const indexHtml = path.join(__dirname, '..', 'public', 'index.html');
      const apiPrefixes = ['/admin/', '/app/', '/open/', '/upload/', '/socket.io/'];
      const staticPrefixes = ['/static/', '/assets/', '/favicon', '/logo'];
      (this.app as any).use(async (ctx: any, next: any) => {
        if (
          ctx.method === 'GET' &&
          ctx.accepts('html') &&
          !apiPrefixes.some((p: string) => ctx.path.startsWith(p)) &&
          !staticPrefixes.some((p: string) => ctx.path.startsWith(p)) &&
          path.extname(ctx.path) === ''
        ) {
          ctx.type = 'text/html';
          ctx.body = fs.readFileSync(indexHtml, 'utf8');
          return;
        }
        await next();
      });
    }
  }
}
