import { spawn } from 'node:child_process';
import * as path from 'node:path';
import * as fs from 'node:fs';

export interface KeyExtractResult {
  seedDir: string;
  wxid: string;
  wechatVersion: string;
  pid: number;
  dbKeys: Record<string, string>;
}

/**
 * 兼容 ESM/CommonJS 拿到当前模块所在目录。
 * - CommonJS: 通过 __dirname 直接获取 (当前项目 tsconfig module=commonjs)
 * - ESM: 通过动态 eval("import.meta") 解析 (避免 commonjs 编译期 syntax error)
 */
function _hereDir(): string | null {
  // CommonJS fallback (本项目主路径)
  if (typeof __dirname !== 'undefined') return __dirname;
  // ESM 动态解析: 用 eval 包一层避免 commonjs 编译期 import.meta syntax error
  try {
    // eslint-disable-next-line no-eval
    const url = (0, eval)('typeof import.meta !== "undefined" ? import.meta.url : undefined');
    if (url) {
      // 延迟 require 避免 commonjs build 把它打进 import 列表
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      const { fileURLToPath } = require('node:url');
      return path.dirname(fileURLToPath(url));
    }
  } catch {
    // ignore
  }
  return null;
}

/**
 * robust 地定位 extract-weixin-key.ps1。按以下顺序 fallback:
 *   1. env NETA_WEIXIN_KEY_SCRIPT
 *   2. 模块自身相对路径 (DEV / pkg 都适用):
 *      key_extractor.ts 在 src/modules/netaclaw/runtime/weixin_db/
 *      → ../../../../tools/win32/extract-weixin-key.ps1
 *   3. installer 部署路径 <installDir>/tools/win32/...
 *   4. 当前工作目录
 */
export function resolveExtractorScript(): string {
  const candidates: string[] = [];

  if (process.env.NETA_WEIXIN_KEY_SCRIPT) candidates.push(process.env.NETA_WEIXIN_KEY_SCRIPT);

  const here = _hereDir();
  if (here) {
    candidates.push(path.resolve(here, '..', '..', '..', '..', 'tools', 'win32', 'extract-weixin-key.ps1'));
  }

  const installDir = process.env.NETA_INSTALL_DIR
    || (process.execPath ? path.dirname(process.execPath) : '');
  if (installDir) {
    candidates.push(path.join(installDir, 'tools', 'win32', 'extract-weixin-key.ps1'));
  }

  candidates.push(path.join(process.cwd(), 'tools', 'win32', 'extract-weixin-key.ps1'));

  for (const c of candidates) {
    if (fs.existsSync(c)) return c;
  }
  throw new Error(
    `extract-weixin-key.ps1 not found. Tried:\n  - ${candidates.join('\n  - ')}\n`
    + `Set NETA_WEIXIN_KEY_SCRIPT env var to override.`
  );
}

export async function extractWeixinKeys(seedDir?: string): Promise<KeyExtractResult> {
  if (process.platform !== 'win32') {
    throw new Error(`extractWeixinKeys only works on win32; current=${process.platform}`);
  }
  const scriptPath = resolveExtractorScript();
  const args = ['-ExecutionPolicy', 'Bypass', '-NoProfile', '-File', scriptPath];
  if (seedDir) { args.push('-SeedDir', seedDir); }

  return await new Promise<KeyExtractResult>((resolve, reject) => {
    const child = spawn('powershell.exe', args, { windowsHide: true });
    let stdout = ''; let stderr = '';
    child.stdout.on('data', d => stdout += d.toString('utf8'));
    child.stderr.on('data', d => stderr += d.toString('utf8'));
    child.on('error', reject);
    child.on('close', code => {
      if (code !== 0) {
        reject(new Error(`extract-weixin-key.ps1 exit ${code}: ${stderr || stdout}`));
        return;
      }
      try {
        resolve(JSON.parse(stdout.trim()) as KeyExtractResult);
      } catch (e: any) {
        reject(new Error(`parse JSON failed: ${e.message} / raw=${stdout.slice(0, 200)}`));
      }
    });
  });
}
