@echo off
setlocal EnableExtensions EnableDelayedExpansion
chcp 65001 >nul
title AgentHub-U XiaoU Desktop Assistant Installer

set "INSTALL_DIR=%USERPROFILE%\.agenthub-agent"
set "LOG_DIR=%INSTALL_DIR%\logs"
set "INSTALL_LOG=%LOG_DIR%\install.log"
set "AGENT_LOG=%LOG_DIR%\agent.log"
set "AGENT_TMP=%INSTALL_DIR%\agent.py.download"
set "CHECKSUM_TMP=%INSTALL_DIR%\checksums.sha256.download"
set "SERVER_URL=https://agenthub-u.com"
set "VENV_DIR=%INSTALL_DIR%\venv"
set "RUNNER=%INSTALL_DIR%\run-agent.bat"
set "LAUNCHER_PS=%INSTALL_DIR%\launch-agent-hidden.ps1"
set "STARTUP_DIR=%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"
set "START_MENU_DIR=%APPDATA%\Microsoft\Windows\Start Menu\Programs\AgentHub-U"
set "STEP_TOTAL=8"

if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%" >nul 2>&1
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%" >nul 2>&1
if not exist "%START_MENU_DIR%" mkdir "%START_MENU_DIR%" >nul 2>&1
> "%INSTALL_LOG%" echo [%date% %time%] AgentHub-U installer started

echo ============================================
echo  AgentHub-U XiaoU Desktop Assistant
echo ============================================
echo.
echo This installer will set up XiaoU Agent on this computer.
echo Windows requires you to open this downloaded installer manually.
echo The Agent will run in the background after setup; the small XiaoU status
echo window will show whether it is online.
echo Log: %INSTALL_LOG%
echo.

call :step 1 "Checking Python 3.8+"
call :find_python
if not defined PYTHON_CMD (
    call :log "Python 3.8+ was not found. Trying to install Python with winget..."
    call :install_python_with_winget
    call :find_python
    if not defined PYTHON_CMD (
        set "FAIL_MESSAGE=Python 3.8+ was not found, and automatic Python install failed. Install Python from https://www.python.org/downloads/ and check Add Python to PATH."
        goto :fatal
    )
)
call :log "Using Python: %PYTHON_CMD%"

call :step 2 "Downloading XiaoU Agent"
del /f "%AGENT_TMP%" >nul 2>&1
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -UseBasicParsing -Uri '%SERVER_URL%/agent/agent.py' -OutFile '%AGENT_TMP%'" >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "PowerShell download failed; retrying with Python..."
    %PYTHON_CMD% -c "import urllib.request; data=urllib.request.urlopen('%SERVER_URL%/agent/agent.py', timeout=45).read(); open(r'%AGENT_TMP%','wb').write(data)" >> "%INSTALL_LOG%" 2>&1
)
if not exist "%AGENT_TMP%" (
    if exist "%INSTALL_DIR%\agent.py" (
        call :log "Download failed, using existing cached agent.py."
    ) else (
        set "FAIL_MESSAGE=Failed to download agent.py. Check internet connection."
        goto :fatal
    )
) else (
    move /y "%AGENT_TMP%" "%INSTALL_DIR%\agent.py" >nul
    if errorlevel 1 (
        set "FAIL_MESSAGE=Failed to write agent.py to the install directory."
        goto :fatal
    )
)
if not exist "%INSTALL_DIR%\agent.py" (
    set "FAIL_MESSAGE=agent.py was not downloaded."
    goto :fatal
)

call :log "Downloading XiaoU mascot asset..."
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -UseBasicParsing -Uri '%SERVER_URL%/agent/xiaou-mascot.png' -OutFile '%INSTALL_DIR%\xiaou-mascot.png'" >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "Mascot asset download failed; desktop status window will use the built-in fallback."
)

call :step 3 "Verifying download security"
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -UseBasicParsing -Uri '%SERVER_URL%/agent/checksums.sha256' -OutFile '%CHECKSUM_TMP%'" >> "%INSTALL_LOG%" 2>&1
if exist "%CHECKSUM_TMP%" move /y "%CHECKSUM_TMP%" "%INSTALL_DIR%\checksums.sha256" >nul
if exist "%INSTALL_DIR%\checksums.sha256" (
    call :log "Verifying checksum..."
    set "EXPECTED_HASH="
    set "ACTUAL_HASH="
    for /f "tokens=1" %%h in ('findstr /i "agent.py" "%INSTALL_DIR%\checksums.sha256"') do if not defined EXPECTED_HASH set "EXPECTED_HASH=%%h"
    if not defined EXPECTED_HASH (
        set "FAIL_MESSAGE=Security check failed: agent.py checksum was not listed."
        goto :fatal
    )
    for /f "skip=1 tokens=1" %%h in ('certutil -hashfile "%INSTALL_DIR%\agent.py" SHA256 2^>nul') do if not defined ACTUAL_HASH set "ACTUAL_HASH=%%h"
    if not defined ACTUAL_HASH (
        call :log "certutil checksum failed; retrying with Python..."
        %PYTHON_CMD% -c "import hashlib,pathlib; print(hashlib.sha256(pathlib.Path(r'%INSTALL_DIR%\agent.py').read_bytes()).hexdigest())" > "%INSTALL_DIR%\agent.sha256.tmp" 2>> "%INSTALL_LOG%"
        if exist "%INSTALL_DIR%\agent.sha256.tmp" set /p ACTUAL_HASH=<"%INSTALL_DIR%\agent.sha256.tmp"
        del /f "%INSTALL_DIR%\agent.sha256.tmp" >nul 2>&1
    )
    if /i not "!ACTUAL_HASH!"=="!EXPECTED_HASH!" (
        set "FAIL_MESSAGE=Security check failed: Checksum mismatch."
        goto :fatal
    )
    del /f "%INSTALL_DIR%\checksums.sha256" >nul 2>&1
) else (
    call :log "Checksum file unavailable; continuing without checksum."
)

echo 正在创建 Python 隔离环境（约10-20秒）...
call :step 4 "Preparing isolated Python environment"
%PYTHON_CMD% -m venv "%VENV_DIR%" >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    set "FAIL_MESSAGE=Failed to create Python virtual environment."
    goto :fatal
)
if not exist "%VENV_DIR%\Scripts\python.exe" (
    set "FAIL_MESSAGE=Virtual environment Python was not created."
    goto :fatal
)
set "VENV_PY=%VENV_DIR%\Scripts\python.exe"

echo 正在安装依赖包（约30-60秒，请耐心等待）...
call :step 5 "Installing required dependency"
"%VENV_PY%" -m pip install --upgrade pip --timeout 120 -i https://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "Aliyun pip upgrade failed; retrying with default PyPI..."
    "%VENV_PY%" -m pip install --upgrade pip --timeout 120 >> "%INSTALL_LOG%" 2>&1
)
"%VENV_PY%" -m pip install websocket-client --timeout 120 -i https://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "Aliyun websocket-client install failed; retrying with default PyPI..."
    "%VENV_PY%" -m pip install websocket-client --timeout 120 >> "%INSTALL_LOG%" 2>&1
)
if errorlevel 1 (
    set "FAIL_MESSAGE=Failed to install websocket-client dependency."
    goto :fatal
)

call :step 6 "Writing background runner"
rem Generated scripts reference %%~dp0 (their own folder) instead of the absolute
rem INSTALL_DIR, so their CONTENT stays pure ASCII. A Chinese Windows username
rem (C:\Users\小明\...) baked into a .bat written under chcp 65001 gets mis-decoded
rem when cmd later runs it, so the agent never starts and the panel stays "未检测到".
rem %%~dp0 is resolved natively at runtime — encoding-proof.
(
echo @echo off
echo setlocal
echo cd /d "%%~dp0"
echo if not exist "%%~dp0logs" mkdir "%%~dp0logs" ^>nul 2^>^&1
echo echo [%%date%% %%time%%] starting AgentHub-U Agent ^>^> "%%~dp0logs\agent.log"
echo "%%~dp0venv\Scripts\python.exe" "%%~dp0agent.py" --server "%SERVER_URL%" ^>^> "%%~dp0logs\agent.log" 2^>^&1
) > "%RUNNER%"

rem $PSScriptRoot = this launcher's own folder (= INSTALL_DIR); keeps content ASCII.
(
echo $runner = Join-Path $PSScriptRoot 'run-agent.bat'
echo $arg = '/c "' + $runner + '"'
echo Start-Process -WindowStyle Minimized -FilePath $env:ComSpec -ArgumentList $arg
) > "%LAUNCHER_PS%"

call :log "Registering auto-start..."
rem Recovery .bat files live OUTSIDE INSTALL_DIR (Startup / Start Menu), so they can't use
rem %%~dp0; they reference %%USERPROFILE%%\.agenthub-agent (ASCII text, expanded at runtime).
(
echo @echo off
echo powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Minimized -File "%%USERPROFILE%%\.agenthub-agent\launch-agent-hidden.ps1"
) > "%STARTUP_DIR%\AgentHub-U.bat"

call :log "Writing Start Menu recovery shortcuts..."
(
echo @echo off
echo powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Minimized -File "%%USERPROFILE%%\.agenthub-agent\launch-agent-hidden.ps1"
) > "%START_MENU_DIR%\Start XiaoU Agent.bat"

(
echo @echo off
echo powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-CimInstance Win32_Process ^| Where-Object { $_.CommandLine -like '*\.agenthub-agent*agent.py*' } ^| Invoke-CimMethod -MethodName Terminate ^| Out-Null"
echo timeout /t 1 /nobreak ^>nul
echo powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Minimized -File "%%USERPROFILE%%\.agenthub-agent\launch-agent-hidden.ps1"
) > "%START_MENU_DIR%\Restart XiaoU Agent.bat"

(
echo @echo off
echo start "" "%%USERPROFILE%%\.agenthub-agent\logs"
) > "%START_MENU_DIR%\Open XiaoU Logs.bat"

call :step 7 "Registering auto-start and recovery"
powershell -NoProfile -ExecutionPolicy Bypass -Command "$script = '%LAUNCHER_PS%'; $arg = '-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File \"' + $script + '\"'; $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument $arg; $trigger = New-ScheduledTaskTrigger -AtLogOn; Register-ScheduledTask -TaskName 'AgentHub-U XiaoU Agent' -Action $action -Trigger $trigger -Description 'Starts XiaoU Agent after Windows sign-in' -Force | Out-Null" >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "Scheduled task registration failed; Startup folder fallback remains active."
) else (
    call :log "Scheduled task registered."
)

call :log "Stopping old Agent processes if any..."
powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^(python|python3|py)\.exe$' -and $_.CommandLine -like '*\.agenthub-agent*agent.py*' } | Invoke-CimMethod -MethodName Terminate | Out-Null" >> "%INSTALL_LOG%" 2>&1

call :step 8 "Starting XiaoU Agent"
powershell -NoProfile -ExecutionPolicy Bypass -WindowStyle Minimized -File "%LAUNCHER_PS%" >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "Hidden launcher failed; falling back to minimized terminal."
    start "AgentHub-U Agent" /min cmd /c ""%RUNNER%""
)

call :log "Waiting for local status server..."
echo This final part is a readiness check, not another dependency install.
echo It can wait up to 60 seconds for XiaoU's local service to become online.
set "AGENT_PORT="
set "SPINNER=|/-\"
for /l %%i in (1,1,60) do (
    set /a "SPIN_INDEX=(%%i-1) %% 4"
    for %%s in (!SPIN_INDEX!) do set "SPIN_CHAR=!SPINNER:~%%s,1!"
    echo [!SPIN_CHAR!] Checking XiaoU local service readiness... %%i/60
    for %%p in (18999 19000 19001 19002 19003) do (
        "%VENV_PY%" -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:%%p/status', timeout=2).read()" >nul 2>> "%INSTALL_LOG%"
        if !ERRORLEVEL! EQU 0 (
            set "AGENT_PORT=%%p"
            goto :agent_ready
        )
    )
    timeout /t 1 /nobreak >nul
)

call :log "Agent did not answer on ports 18999-19003."
echo.
echo [ERROR] Agent did not start correctly.
echo Please send this log to support:
echo %INSTALL_LOG%
echo.
powershell -NoProfile -Command "Get-Content -Tail 30 '%INSTALL_LOG%'"
pause
exit /b 1

:agent_ready
call :log "Agent status server is running on port %AGENT_PORT%."
echo.
echo ============================================
echo  Installed successfully
echo ============================================
echo Agent is running on http://localhost:%AGENT_PORT%/status
echo A small XiaoU status window will stay on the desktop.
echo Please keep XiaoU running while installing or launching tools.
echo Return to the browser panel and click recheck.
echo.
echo Logs:
echo   %INSTALL_LOG%
echo   %AGENT_LOG%
echo.
echo ============================================
echo  小U已启动！请不要关闭此窗口。
echo  如需关闭，请确认浏览器面板已能检测到小U在线。
echo ============================================
echo.
echo 如果浏览器面板仍显示"未检测到小U"：
echo   1. 等待10秒后刷新面板页面
echo   2. 或从开始菜单 → AgentHub-U → Start XiaoU Agent
echo   3. 查看日志: %AGENT_LOG%
echo.
pause
exit /b 0

:find_python
call :try_python "py -3"
if defined PYTHON_CMD exit /b 0
call :try_python "python"
if defined PYTHON_CMD exit /b 0
call :try_python "python3"
exit /b 0

:try_python
set "CANDIDATE=%~1"
%CANDIDATE% -c "import sys; raise SystemExit(0 if sys.version_info >= (3,8) else 1)" >nul 2>> "%INSTALL_LOG%"
if !ERRORLEVEL! EQU 0 set "PYTHON_CMD=%CANDIDATE%"
exit /b 0

:install_python_with_winget
where winget >nul 2>&1
if errorlevel 1 (
    call :log "winget not available; downloading Python installer directly..."
    goto :install_python_direct
)
winget install --id Python.Python.3.12 -e --scope user --silent --accept-package-agreements --accept-source-agreements >> "%INSTALL_LOG%" 2>&1
if errorlevel 1 (
    call :log "winget Python install failed; falling back to direct download..."
    goto :install_python_direct
)
call :add_python_to_path
exit /b 0

:install_python_direct
rem winget missing/failed (older Win10, App Installer stripped, enterprise image).
rem A non-technical user cannot 'go install Python' — download + silent-install it.
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -UseBasicParsing -Uri 'https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe' -OutFile '%INSTALL_DIR%\python-setup.exe'" >> "%INSTALL_LOG%" 2>&1
if not exist "%INSTALL_DIR%\python-setup.exe" (
    call :log "Direct Python installer download failed."
    exit /b 1
)
"%INSTALL_DIR%\python-setup.exe" /quiet InstallAllUsers=0 PrependPath=1 Include_launcher=1 >> "%INSTALL_LOG%" 2>&1
call :add_python_to_path
del /f "%INSTALL_DIR%\python-setup.exe" >nul 2>&1
exit /b 0

:add_python_to_path
rem Don't hard-code Python312 — scan for any user-scope Python3* so a 3.13 install
rem (or a different minor) is still found in this un-refreshed cmd session.
for /d %%D in ("%LOCALAPPDATA%\Programs\Python\Python3*") do (
    if exist "%%D\python.exe" set "PATH=%%D;%%D\Scripts;!PATH!"
)
if exist "%ProgramFiles%\Python312\python.exe" set "PATH=%ProgramFiles%\Python312;%ProgramFiles%\Python312\Scripts;!PATH!"
exit /b 0

:log
echo [*] %~1
>> "%INSTALL_LOG%" echo [%date% %time%] %~1
exit /b 0

:step
echo.
echo [%~1/%STEP_TOTAL%] %~2
>> "%INSTALL_LOG%" echo [%date% %time%] STEP %~1/%STEP_TOTAL%: %~2
exit /b 0

:fatal
echo.
echo [ERROR] %FAIL_MESSAGE%
>> "%INSTALL_LOG%" echo [%date% %time%] ERROR: %FAIL_MESSAGE%
echo.
echo Install failed. Log file:
echo %INSTALL_LOG%
echo.
powershell -NoProfile -Command "Get-Content -Tail 30 '%INSTALL_LOG%'" 2>nul
pause
exit /b 1
