#!/usr/bin/env node

/**
 * ============================================================================
 * MyClaw WSL2 一键安装器
 * ============================================================================
 *
 * 采用"固定流程 + 状态标记"机制，避免使用容易出错的环境嗅探（wsl --status）。
 * 标记文件：~/.myclaw_wsl_state
 *
 * Phase 1: 启用底层功能 + 安装 WSL + 下载 Linux 镜像 → 需要重启
 * Phase 2: 导入已下载的 Linux 环境 → 自动启动 Gateway（极快）
 * ============================================================================
 */

const { execSync } = require('child_process');
const os = require('os');
const fs = require('fs');
const path = require('path');

// ============================================================================
// 配置
// ============================================================================

const WSL_CDN = {
  wsl: 'https://cdn.yiranlaoshi.com/software/myclaw/wsl.2.7.1.0.x64.msi',
  rootfs: 'https://cdn.yiranlaoshi.com/software/myclaw/openclaw-rootfs.tar',
};

const isWindows = os.platform() === 'win32';

const C = isWindows
  ? { r: '', g: '', y: '', b: '', nc: '' }
  : { r: '\x1b[31m', g: '\x1b[32m', y: '\x1b[33m', b: '\x1b[34m', nc: '\x1b[0m' };

const STATE_FILE = path.join(os.homedir(), '.myclaw_wsl_state');
const MARKER_PATH_PS = STATE_FILE.replace(/\\/g, '\\\\');

const CONFIG_FILE = path.join(os.homedir(), '.myclaw_config');

const WORK_DIR = path.join(os.homedir(), '.myclaw_tmp');
try { fs.mkdirSync(WORK_DIR, { recursive: true }); } catch {}
const WORK_DIR_PS = WORK_DIR.replace(/\\/g, '\\\\');

// ============================================================================
// 工具函数
// ============================================================================

function getState() {
  if (fs.existsSync(STATE_FILE)) {
    return fs.readFileSync(STATE_FILE, 'utf8').trim();
  }
  return 'needs-features';
}

function setState(state) {
  fs.writeFileSync(STATE_FILE, state, 'utf8');
}

function getConfig() {
  try {
    if (fs.existsSync(CONFIG_FILE)) {
      const content = fs.readFileSync(CONFIG_FILE, 'utf8');
      return JSON.parse(content);
    }
  } catch {}
  return {};
}

function setConfig(key, value) {
  const config = getConfig();
  config[key] = value;
  fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf8');
}

function launchElevatedPS(script) {
  const tmpDir = process.env.LOCALAPPDATA
    ? path.join(process.env.LOCALAPPDATA, 'myclaw')
    : path.join(os.tmpdir(), 'myclaw');
  try { fs.mkdirSync(tmpDir, { recursive: true }); } catch {}
  const scriptPath = path.join(tmpDir, 'wsl2_installer.ps1');

  // UTF-8 with BOM
  const BOM = '\uFEFF';
  fs.writeFileSync(scriptPath, BOM + script, 'utf8');

  const escaped = scriptPath.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
  const cmd = `powershell -Command "Start-Process powershell -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-NoExit','-File','${escaped}') -Verb RunAs"`;

  try {
    execSync(cmd, { stdio: 'inherit' });
    return true;
  } catch (err) {
    console.error('[' + C.r + '错误' + C.nc + '] 无法获取管理员权限: ' + err.message);
    console.log('建议右键终端选择【以管理员身份运行】后重试。');
    return false;
  }
}

function makeAskLocalOrCDN(prompt, destVar, cdnUrl, desc, fileName, forceRemote) {
  const config = getConfig();
  const callerDir = (config.installerDir || process.env.MYCLAW_INSTALLER_DIR || process.cwd()).replace(/\\/g, '\\\\');
  const cdnFilename = cdnUrl.split('/').pop();

  // --remote 模式：跳过所有本地检测，直接从 CDN 下载
  if (forceRemote) {
    return `
Write-Host ""
Write-Host "  [强制远程] 跳过本地文件检测，从网络下载..."
Write-Host ""
Write-Host '      -------------------------------------------------------------'
Write-Host '      [提示] 下载中请勿点击窗口内部（会导致卡死）。'
Write-Host '      [恢复] 若进度条长时间不动，请按一下 [回车键] 即可恢复。'
Write-Host '      -------------------------------------------------------------'
try {
    Start-BitsTransfer -Source '${cdnUrl}' -Destination ${destVar} -Description '下载 ${desc}' -DisplayName 'OpenClaw'
    Write-Host '      下载完成!'
} catch {
    Write-Host '      [失败] 下载失败，请检查网络后重试'
    throw '下载失败'
}
`;
  }

  return `
$callerDir = "${callerDir}"

$autoLocal1 = Join-Path $callerDir "${cdnFilename}"
$autoLocal2 = Join-Path $callerDir "${fileName}"

$autoFound = ""

if (Test-Path $autoLocal1 -PathType Leaf) {
    $autoFound = $autoLocal1
} elseif (Test-Path $autoLocal2 -PathType Leaf) {
    $autoFound = $autoLocal2
}

if ($autoFound) {
    Write-Host ""
    Write-Host "  [自动检测] 发现本地文件并跳过询问: $autoFound"
    $resolved = $autoFound
} else {
    Write-Host ''
    Write-Host '  +---------------------------------------------+'
    Write-Host '  |  ${desc}                                    '
    Write-Host '  |                                             '
    Write-Host '  |  [1] 拖拽文件到此窗口 + 回车               '
    Write-Host '  |  [2] 输入U盘盘符 (如 F) + 回车 -> 自动搜索 '
    Write-Host '  |  [3] 直接回车 -> 从网络下载                 '
    Write-Host '  +---------------------------------------------+'
    Write-Host ''
    $userInput = Read-Host '  请输入路径/盘符/回车'
    $userInput = $userInput.Trim().Trim('"')
    $resolved = ''

    if ($userInput) {
        if ($userInput -match '^[a-zA-Z]$') {
            $drive = $userInput.ToUpper()
            $drivePath = $drive + ':'
            Write-Host "      正在搜索 $drivePath 中的 ${fileName}..."
            $found = Get-ChildItem -Path $drivePath -Filter '${fileName}' -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
            if ($found) {
                Write-Host "      找到: $($found.FullName)"
                $resolved = $found.FullName
            } else {
                Write-Host "      未在 $drivePath 中找到 ${fileName}"
            }
        } elseif (Test-Path $userInput -PathType Leaf) {
            $resolved = $userInput
        } elseif (Test-Path $userInput -PathType Container) {
            Write-Host "      正在搜索 $userInput 中的 ${fileName}..."
            $found = Get-ChildItem -Path $userInput -Filter '${fileName}' -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
            if ($found) {
                Write-Host "      找到: $($found.FullName)"
                $resolved = $found.FullName
            } else {
                Write-Host "      未在该目录中找到 ${fileName}"
            }
        } else {
            Write-Host "      [警告] 路径不存在: $userInput"
        }
    }
}

if ($resolved) {
    Write-Host "      使用本地文件: $resolved"
    Copy-Item $resolved ${destVar} -Force
    Write-Host '      [OK]'
} else {
    if ($userInput) {
        Write-Host '      将改为从网络下载...'
    }
    Write-Host ''
    Write-Host '      -------------------------------------------------------------'
    Write-Host '      [提示] 下载中请勿点击窗口内部（会导致卡死）。'
    Write-Host '      [恢复] 若进度条长时间不动，请按一下 [回车键] 即可恢复。'
    Write-Host '      -------------------------------------------------------------'
    try {
        Start-BitsTransfer -Source '${cdnUrl}' -Destination ${destVar} -Description '下载 ${desc}' -DisplayName 'OpenClaw'
        Write-Host '      下载完成!'
    } catch {
        Write-Host '      [失败] 下载失败，请检查网络后重试'
        throw '下载失败'
    }
}
`;
}

// ============================================================================
// Phase 1: 启用功能 + 安装 WSL + 下载 Linux 镜像（全部在重启前完成）
// ============================================================================

function runPhase1(forceRemote) {
  console.log('');
  console.log('[当前进度] WSL 功能     ' + C.y + '[安装/覆盖]' + C.nc);
  console.log('           WSL 组件     ' + C.y + '[安装/重置]' + C.nc);
  console.log('           Linux 镜像   ' + C.y + '[待下载]' + C.nc);
  console.log('           Linux 环境   ' + C.r + '[未安装]' + C.nc);
  console.log('');
  console.log('阶段 1/2: 配置系统组件 + 下载全部安装素材');
  console.log('  完成后需要 ' + C.y + '重启电脑' + C.nc);
  console.log('');
  console.log('[' + C.y + '注意' + C.nc + '] 请在 UAC 弹窗中点击【是】');
  console.log('');

  const askMsi = makeAskLocalOrCDN(
    '拖拽 WSL 安装包或回车下载',
    '$msi',
    WSL_CDN.wsl,
    'WSL 安装包 (wsl_full.msi)',
    'wsl_full.msi',
    forceRemote
  );

  const askTar = makeAskLocalOrCDN(
    '拖拽 tar 包或回车下载',
    '$tarPath',
    WSL_CDN.rootfs,
    'Linux 环境包 (openclaw-rootfs.tar)',
    'openclaw-rootfs.tar',
    forceRemote
  );

  const ps = `
$ErrorActionPreference = 'Continue'
$Host.UI.RawUI.WindowTitle = 'MyClaw WSL2 Installer - Phase 1'
try {
Write-Host ''
Write-Host '========================================'
Write-Host '  MyClaw WSL2 安装 - 阶段 1/2'
Write-Host '  配置系统 + 下载全部安装素材'
Write-Host '========================================'
Write-Host ''

$dir = "${WORK_DIR_PS}"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
$msi = "$dir\\\\wsl_full.msi"
$tarPath = "$dir\\\\openclaw-rootfs.tar"

Write-Host '[1/5] 启用 Windows Subsystem for Linux...'
try {
    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart | Out-Null
    Write-Host '      [OK]'
} catch {
    Write-Host '      [异常] 启用失败，继续尝试...'
}
Write-Host ''

Write-Host '[2/5] 启用虚拟机平台...'
try {
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart | Out-Null
    Write-Host '      [OK]'
} catch {
    Write-Host '      [异常] 启用失败，继续尝试...'
}
Write-Host ''

Write-Host '[3/5] 获取 WSL 安装包...'
if (Test-Path $msi) { Remove-Item $msi -Force }

${askMsi}

Write-Host ''
Write-Host '[4/5] 强制覆盖安装 WSL...'
try {
    Start-Process msiexec.exe -ArgumentList @('/i', $msi, '/quiet', '/norestart') -Wait -NoNewWindow
    if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne 3010) {
        Write-Host "      [警告] 安装退出代码异常 (Code: $LASTEXITCODE)"
    } else {
        Write-Host '      [OK]'
    }
} catch {
    Write-Host '      [失败] 安装出错'
    throw 'MSI 安装失败'
}

# MSI 装完立即删除
if (Test-Path $msi) { Remove-Item $msi -Force }
Write-Host ''

Write-Host '[5/5] 下载 Linux 环境镜像...'
Write-Host '      (此文件较大，下载完成后会保留到重启后使用)'
if (Test-Path $tarPath) { Remove-Item $tarPath -Force }

${askTar}

# 写入状态标记（使用普通用户路径）
$markerPath = "${MARKER_PATH_PS}"
Out-File -FilePath "$markerPath" -InputObject "phase1-done" -Encoding utf8 -Force

Write-Host ''
Write-Host '========================================'
Write-Host '  阶段 1/2 完成! 所有文件已准备就绪!'
Write-Host ''
Write-Host '  >>> 需要重启电脑才能继续安装 <<<'
Write-Host ''
$answer = Read-Host '  是否立即重启? 请先保存好其他工作 (y/n)'
if ($answer -match '^[Yy]') {
    Write-Host '  正在重启...'
    Restart-Computer -Force
} else {
    Write-Host ''
    Write-Host '  请手动重启电脑，重启后点击桌面 [龙虾图标] 继续安装'
}
Write-Host '========================================'

} catch {
    Write-Host ''
    Write-Host '========================================'
    Write-Host "  [异常] 发生错误: $_"
    Write-Host '  请截图此窗口内容后联系老师'
    Write-Host '========================================'
} finally {
    Write-Host ''
    Write-Host '按任意键关闭此窗口...'
    $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
}
`;

  if (launchElevatedPS(ps)) {
    console.log('[' + C.g + '已启动' + C.nc + '] 请查看新弹出的蓝色窗口');
    console.log('');
    console.log('执行完请 ' + C.y + '重启电脑' + C.nc + '，然后点击桌面上的 ' + C.y + '龙虾图标' + C.nc + ' 继续安装');
    console.log('');
  }
}

// ============================================================================
// Phase 2: 导入已下载的 Linux 环境（重启后，纯本地操作，极快）
// ============================================================================

function runPhase2(forceRemote) {
  console.log('');
  console.log('[当前进度] WSL 功能     ' + C.g + '[已就绪]' + C.nc);
  console.log('           WSL 组件     ' + C.g + '[已就绪]' + C.nc);
  console.log('           Linux 镜像   ' + C.g + '[已下载]' + C.nc);
  console.log('           Linux 环境   ' + C.y + '[待导入]' + C.nc);
  console.log('');
  console.log('即将导入预制 Linux 环境（纯本地操作，很快）...');
  console.log('[' + C.y + '注意' + C.nc + '] 请在 UAC 弹窗中点击【是】');
  console.log('');

  const ps = `
$ErrorActionPreference = 'Continue'
$Host.UI.RawUI.WindowTitle = 'MyClaw WSL2 Installer - Phase 2'
try {
Write-Host ''
Write-Host '========================================'
Write-Host '  MyClaw WSL2 安装 - 阶段 2/2'
Write-Host '  导入预制 Linux 环境'
Write-Host '========================================'
Write-Host ''

$dir = "${WORK_DIR_PS}"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
$tarPath = "$dir\\\\openclaw-rootfs.tar"
$distroName = 'OpenClaw'
$installDir = "$dir\\\\OpenClaw"
$installed = $false

Write-Host '[1/4] 设置 WSL2 为默认版本...'
try { wsl --set-default-version 2 2>$null } catch {}
Write-Host '      [OK]'
Write-Host ''

Write-Host '[2/4] 检查 Linux 镜像文件...'
if (Test-Path $tarPath) {
    $size = (Get-Item $tarPath).Length / 1MB
    Write-Host "      找到本地镜像 ($([math]::Round($size, 1)) MB)"
    Write-Host '      [OK]'
} else {
    Write-Host '      [警告] 未找到已下载的镜像文件，需要重新获取...'
    Write-Host ''
    ${makeAskLocalOrCDN(
      '拖拽 tar 包或回车下载',
      '$tarPath',
      WSL_CDN.rootfs,
      'Linux 环境包 (openclaw-rootfs.tar)',
      'openclaw-rootfs.tar',
      forceRemote
    )}
}
Write-Host ''

Write-Host '[3/4] 导入 Linux 环境 (可能需要几分钟)...'
Write-Host '      清理旧版本...'
try { wsl --unregister $distroName 2>&1 | Out-Null } catch {}
Write-Host '      [OK]'

try {
    New-Item -ItemType Directory -Force -Path $installDir | Out-Null
    wsl --import $distroName $installDir $tarPath 2>$null
    if ($LASTEXITCODE -eq 0) {
        $installed = $true
        Write-Host '      [OK] 导入成功!'
    } else {
        Write-Host '      [失败] 导入失败'
    }
} catch {
    Write-Host '      [失败] 导入失败'
}
Write-Host ''

# 导入完毕清理 tar 文件
if (Test-Path $tarPath) { Remove-Item $tarPath -Force }

Write-Host '[4/4] 验证安装结果...'
try {
    $result = wsl -l -v 2>&1 | Out-String
    Write-Host $result
} catch {
    Write-Host '      无法获取信息'
}

Write-Host ''
Write-Host '========================================'
if ($installed) {
    Write-Host '  [OK] WSL2 + OpenClaw Linux 安装完成!'
    Write-Host '========================================'
    Write-Host ''

    $markerPath = "${MARKER_PATH_PS}"
    Out-File -FilePath "$markerPath" -InputObject "phase2-done" -Encoding utf8 -Force

    Write-Host '[镜像信息]'
    try {
        $buildInfo = wsl -d $distroName -- cat /etc/openclaw-build-info 2>&1
        Write-Host $buildInfo
    } catch {
        Write-Host '  (无构建信息)'
    }
    Write-Host ''

    wsl -d $distroName -- myclaw launch
} else {
    Write-Host '  [失败] 请截图此窗口并联系老师'
    Write-Host '========================================'
}

} catch {
    Write-Host ''
    Write-Host '========================================'
    Write-Host "  [异常] 发生错误: $_"
    Write-Host '  请截图此窗口内容后联系老师'
    Write-Host '========================================'
} finally {
    Write-Host ''
    Write-Host '按任意键关闭此窗口...'
    $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
}
`;

  if (launchElevatedPS(ps)) {
    console.log('[' + C.g + '已启动' + C.nc + '] 请查看新弹出的蓝色窗口');
    console.log('');
    console.log('安装完成后会自动启动 Gateway 并打开浏览器');
    console.log('');
  }
}

// ============================================================================
// ============================================================================
// CLI 模式
// ============================================================================

function runCliMode() {
  const readline = require('readline');
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });

  const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));

  async function showMenu() {
    console.log('');
    console.log('========================================');
    console.log('  MyClaw WSL2 CLI 控制面板');
    console.log('========================================');
    console.log('');

    const config = getConfig();
    const currentPath = config.installerDir || '(未设置)';

    console.log('当前安装包路径: ' + C.y + currentPath + C.nc);
    console.log('');
    console.log('请选择操作:');
    console.log('  1. 重新安装 Phase 1 (启用功能 + 下载)');
    console.log('  2. 重新安装 Phase 2 (导入 Linux 环境)');
    console.log('  3. 重新设置安装包路径');
    console.log('  4. WSL2虚拟机重装 (强制远程 + 阶段1重启)');
    console.log('  0. 退出');
    console.log('');

    const choice = await question('请输入选项 (0-4): ');

    switch (choice.trim()) {
      case '1':
        console.log('');
        console.log('[' + C.y + '执行' + C.nc + '] 开始 Phase 1 安装...');
        setState('needs-features');
        rl.close();
        runPhase1(false);
        break;

      case '2':
        console.log('');
        console.log('[' + C.y + '执行' + C.nc + '] 开始 Phase 2 安装...');
        setState('phase1-done');
        rl.close();
        runPhase2(false);
        break;

      case '3':
        console.log('');
        const newPath = await question('请输入安装包存放路径: ');
        if (newPath.trim()) {
          setConfig('installerDir', newPath.trim());
          console.log('');
          console.log('[' + C.g + 'OK' + C.nc + '] 路径已保存: ' + C.y + newPath.trim() + C.nc);
          console.log('');
          console.log('再次运行 ' + C.y + 'myclaw wsl2' + C.nc + ' 时将使用此路径。');
        } else {
          console.log('[' + C.r + '取消' + C.nc + '] 路径为空，未保存。');
        }
        rl.close();
        break;

      case '4':
        console.log('');
        console.log('[' + C.y + '执行' + C.nc + '] WSL2虚拟机重装 (强制远程下载)...');
        console.log('');
        setState('needs-features');
        rl.close();
        runPhase1(true);
        break;

      case '0':
        console.log('');
        console.log('已退出。');
        rl.close();
        break;

      default:
        console.log('');
        console.log('[' + C.r + '错误' + C.nc + '] 无效选项，请重试。');
        await showMenu();
        break;
    }
  }

  showMenu();
}

// ============================================================================
// 主入口
// ============================================================================

function run() {
  if (!isWindows) {
    console.error('[提示] 本命令仅用于 Windows 系统。Mac/Linux 不需要 WSL2。');
    process.exit(0);
  }

  // CLI 模式
  if (process.argv.includes('--cli')) {
    runCliMode();
    return;
  }

  // 隐藏的高级玩家后门
  if (process.argv.includes('--force-phase1')) {
    setState('needs-features');
  }
  if (process.argv.includes('--force-phase2')) {
    setState('phase1-done');
  }

  // --remote: 强制从 CDN 下载，不信任本地文件
  const forceRemote = process.argv.includes('--remote');

  const bar = '========================================';
  const state = getState();

  console.log('');
  console.log('[' + C.b + 'MyClaw' + C.nc + '] WSL2 一键安装向导');
  console.log(bar);

  if (state === 'phase2-done') {
    console.log('');
    console.log('[' + C.g + 'OK' + C.nc + '] WSL2 已完全安装就绪！');
    console.log('');
    try {
      const info = execSync('wsl -l -v', { stdio: 'pipe' }).toString('utf16le');
      console.log(info.trim());
    } catch {
      console.log('（运行 wsl -l -v 查看详情）');
    }
    console.log('');
    console.log('点击桌面上的 ' + C.y + '龙虾图标' + C.nc + ' 即可启动。');
    console.log('');

    const readline = require('readline');
    const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
    rl.question('是否要重置状态并完全重新走安装流程? (y/N): ', (answer) => {
      rl.close();
      if (answer.trim().toLowerCase() === 'y') {
        console.log('');
        console.log('[' + C.y + '重置模式' + C.nc + '] 将删除标记文件并从 Phase 1 重新开始...');
        setState('needs-features');
        runPhase1();
      } else {
        console.log('');
        console.log('已取消。');
      }
    });
    return;
  }

  if (state === 'phase1-done') {
    runPhase2(forceRemote);
  } else {
    runPhase1(forceRemote);
  }
}

module.exports = { run };
