@echo off
setlocal EnableExtensions DisableDelayedExpansion
chcp 65001 >nul 2>nul
title Xiaoqi Claw Upgrade 1.0.8 to 1.0.9

set "FROM_VERSION=1.0.8"
set "TO_VERSION=1.0.9"
set "BASE_URL=https://www.xiaoqiclaw.cloud/downloads"
set "BOOTSTRAP_FILE=xiaoqi-claw-transition-runtime-1.0.8.zip"
set "BOOTSTRAP_URL=%BASE_URL%/%BOOTSTRAP_FILE%"
set "PACKAGE_URL=%BASE_URL%/xiaoqi-claw-transition-%FROM_VERSION%-to-%TO_VERSION%.zip"
set "EXPECTED_BOOTSTRAP_SHA256=FB2DD666EC23081327B68417F04704E09968F52D5BCACD0BC9B1C6E5D2DB401C"
set "EXPECTED_PACKAGE_SHA256=5CCD56C6BF222D5BA1AD29827F52DAB56F9084ABBABDC34FC1470576489900C8"
set "REQUESTED_ROOT="
set "CHECK_ONLY=0"

:parse_args
if "%~1"=="" goto :args_done
if /I "%~1"=="--check-only" (
  set "CHECK_ONLY=1"
  shift
  goto :parse_args
)
if /I "%~1"=="--drive" (
  if "%~2"=="" goto :bad_args
  set "REQUESTED_ROOT=%~2"
  shift
  shift
  goto :parse_args
)
goto :bad_args

:args_done
echo.
echo ======================================================
echo       Xiaoqi Claw Upgrade %FROM_VERSION% to %TO_VERSION%
echo ======================================================
echo.
echo This is a normal product upgrade, not a repair package.
echo Downloading never changes the USB. Installation starts only after SHA-256 and official signature verification pass.
echo If the network is interrupted, run this BAT again. curl resumes the partial download when supported.
echo.
echo [1/7] Detecting the Xiaoqi Claw USB drive...

set "ROOT="
set "ROOT_COUNT=0"
if defined REQUESTED_ROOT goto :resolve_requested_root

set "SCRIPT_ROOT=%~d0\"
call :is_transition_root "%SCRIPT_ROOT%"
if not errorlevel 1 (
  set "ROOT=%SCRIPT_ROOT%"
  goto :root_ready
)

set "AIU_FROM_VERSION=%FROM_VERSION%"
set "AIU_TO_VERSION=%TO_VERSION%"
for /f "usebackq tokens=1,* delims=|" %%A in (`powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command "$ErrorActionPreference='SilentlyContinue'; $all=@(); $seen=@{}; foreach($drive in @(Get-PSDrive -PSProvider FileSystem)) { try { $r=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath([string]$drive.Root)); if ([string]::IsNullOrWhiteSpace($r)) { continue }; $separator=[IO.Path]::DirectorySeparatorChar.ToString(); if (-not $r.EndsWith($separator)) { $r += $separator }; $key=$r.ToUpperInvariant(); if ($seen.ContainsKey($key)) { continue }; $seen[$key]=$true; $version=Join-Path $r 'XIAOQI_CLAW_VERSION'; if (-not ((Test-Path -LiteralPath $version -PathType Leaf) -and (Test-Path -LiteralPath (Join-Path $r 'manager\server.js') -PathType Leaf) -and (Test-Path -LiteralPath (Join-Path $r 'portable-license-public.pem') -PathType Leaf))) { continue }; $v=[IO.File]::ReadAllText($version).Trim(); $rank=2; if ($v -eq $env:AIU_FROM_VERSION) { $rank=0 } elseif ($v -eq $env:AIU_TO_VERSION) { $rank=1 }; $all += [PSCustomObject]@{Root=$r; Rank=$rank} } catch {} }; if ($all.Count -eq 0) { exit 0 }; $best=2; foreach($item in $all) { if ($item.Rank -lt $best) { $best=$item.Rank } }; foreach($item in $all) { if ($item.Rank -eq $best) { [Console]::Out.WriteLine('XIAOQI_ROOT'+[char]124+$item.Root) } }"`) do (
  if /I "%%A"=="XIAOQI_ROOT" (
    set /a ROOT_COUNT+=1 >nul
    set "ROOT=%%B"
    echo [FOUND] Candidate Xiaoqi Claw drive: %%B
  )
)
if not defined ROOT goto :root_not_found
if %ROOT_COUNT% GTR 1 goto :multiple_roots
goto :root_ready

:resolve_requested_root
set "AIU_REQUESTED_ROOT=%REQUESTED_ROOT%"
for /f "usebackq delims=" %%D in (`powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "try { $p=[IO.Path]::GetFullPath($env:AIU_REQUESTED_ROOT); [IO.Path]::GetPathRoot($p) } catch { exit 1 }"`) do set "ROOT=%%D"
if not defined ROOT goto :root_not_found
if not exist "%ROOT%XIAOQI_CLAW_VERSION" goto :root_not_found
if not exist "%ROOT%manager\server.js" goto :root_not_found
if not exist "%ROOT%portable-license-public.pem" goto :root_not_found

:root_ready
set "CURRENT_VERSION="
set /p CURRENT_VERSION=<"%ROOT%XIAOQI_CLAW_VERSION"
if "%CURRENT_VERSION%"=="%TO_VERSION%" goto :already_latest
if not "%CURRENT_VERSION%"=="%FROM_VERSION%" goto :unsupported_version
echo [OK] USB drive found: %ROOT%
echo [OK] Current version: %CURRENT_VERSION%

set "WORK=%TEMP%\XiaoqiClaw-Upgrade-%FROM_VERSION%-to-%TO_VERSION%"
set "BOOTSTRAP_ZIP=%WORK%\%BOOTSTRAP_FILE%"
set "BOOTSTRAP_DIR=%WORK%\runtime"
set "PACKAGE=%WORK%\xiaoqi-claw-transition-%FROM_VERSION%-to-%TO_VERSION%.zip"
set "PACKAGE_CACHE_MARKER=%WORK%\package-sha256.txt"
set "AIU_BOOTSTRAP_ZIP=%BOOTSTRAP_ZIP%"
set "AIU_BOOTSTRAP_DIR=%BOOTSTRAP_DIR%"

if exist "%WORK%\." goto :workspace_ready
mkdir "%WORK%" >nul 2>nul
if errorlevel 1 goto :temp_failed
:workspace_ready
if not exist "%WORK%\." goto :temp_failed

set "CACHED_PACKAGE_SHA256="
if exist "%PACKAGE_CACHE_MARKER%" set /p CACHED_PACKAGE_SHA256=<"%PACKAGE_CACHE_MARKER%"
if /I "%CACHED_PACKAGE_SHA256%"=="%EXPECTED_PACKAGE_SHA256%" goto :package_cache_ready
if exist "%PACKAGE%" echo [CACHE] Removing an older upgrade package download...
if exist "%PACKAGE%" del /f /q "%PACKAGE%" >nul 2>nul
if exist "%PACKAGE%" goto :stale_cache_failed
>"%PACKAGE_CACHE_MARKER%" echo %EXPECTED_PACKAGE_SHA256%
set "CACHED_PACKAGE_SHA256="
set /p CACHED_PACKAGE_SHA256=<"%PACKAGE_CACHE_MARKER%"
if /I not "%CACHED_PACKAGE_SHA256%"=="%EXPECTED_PACKAGE_SHA256%" goto :temp_failed
:package_cache_ready

echo.
echo [2/7] Downloading the independent secure updater...
call :ensure_download "%BOOTSTRAP_URL%" "%BOOTSTRAP_ZIP%" "%EXPECTED_BOOTSTRAP_SHA256%"
if errorlevel 1 goto :bootstrap_download_failed

if exist "%BOOTSTRAP_DIR%" rmdir /s /q "%BOOTSTRAP_DIR%" >nul 2>nul
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop'; Expand-Archive -LiteralPath $env:AIU_BOOTSTRAP_ZIP -DestinationPath $env:AIU_BOOTSTRAP_DIR -Force"
if errorlevel 1 goto :bootstrap_extract_failed
if not exist "%BOOTSTRAP_DIR%\node.exe" goto :bootstrap_incomplete
if not exist "%BOOTSTRAP_DIR%\updater\apply-update.js" goto :bootstrap_incomplete
if not exist "%BOOTSTRAP_DIR%\portable-license-public.pem" goto :bootstrap_incomplete

echo.
echo [3/7] Downloading the signed %FROM_VERSION% to %TO_VERSION% upgrade package...
call :ensure_download "%PACKAGE_URL%" "%PACKAGE%" "%EXPECTED_PACKAGE_SHA256%"
if errorlevel 1 goto :package_download_failed

echo.
echo [4/7] Verifying the official signature and every packaged file...
"%BOOTSTRAP_DIR%\node.exe" "%BOOTSTRAP_DIR%\updater\apply-update.js" verify --package "%PACKAGE%" --public-key "%BOOTSTRAP_DIR%\portable-license-public.pem"
if errorlevel 1 goto :package_verify_failed
if "%CHECK_ONLY%"=="1" goto :check_passed

echo.
echo [5/7] Stopping Xiaoqi Claw services. Do not unplug the USB...
echo [6/7] Installing the verified upgrade. Network is no longer required...
"%BOOTSTRAP_DIR%\node.exe" "%BOOTSTRAP_DIR%\updater\apply-update.js" worker --target "%ROOT%." --package "%PACKAGE%" --public-key "%BOOTSTRAP_DIR%\portable-license-public.pem"
set "UPDATE_RESULT=%errorlevel%"
if not "%UPDATE_RESULT%"=="0" goto :update_failed

echo.
echo [7/7] Cleaning temporary download files...
rmdir /s /q "%WORK%" >nul 2>nul
echo.
echo ======================================================
echo   Upgrade completed. Xiaoqi Claw is now %TO_VERSION%.
echo ======================================================
echo Customer settings, chats, license, generated files and voice settings were preserved.
echo.
pause
exit /b 0

:ensure_download
call :verify_sha256 "%~2" "%~3"
if not errorlevel 1 exit /b 0
set "AIU_DOWNLOAD_URL=%~1"
set "AIU_DOWNLOAD_OUT=%~2"
where curl.exe >nul 2>nul
if errorlevel 1 goto :download_full
curl.exe -fL --retry 5 --retry-delay 2 --connect-timeout 20 --continue-at - --progress-bar --output "%~2" "%~1"
call :verify_sha256 "%~2" "%~3"
if not errorlevel 1 exit /b 0

:download_full
if exist "%~2" del /f /q "%~2" >nul 2>nul
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -UseBasicParsing -Uri $env:AIU_DOWNLOAD_URL -OutFile $env:AIU_DOWNLOAD_OUT"
if errorlevel 1 exit /b 1
call :verify_sha256 "%~2" "%~3"
exit /b %errorlevel%

:verify_sha256
if not exist "%~1" exit /b 1
set "ACTUAL_SHA256="
set "AIU_VERIFY_FILE=%~1"
for /f "usebackq delims=" %%H in (`powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "try { (Get-FileHash -LiteralPath $env:AIU_VERIFY_FILE -Algorithm SHA256).Hash } catch { exit 1 }"`) do set "ACTUAL_SHA256=%%H"
if not defined ACTUAL_SHA256 exit /b 1
if /I not "%ACTUAL_SHA256%"=="%~2" exit /b 1
exit /b 0

:is_transition_root
if "%~1"=="" exit /b 1
if not exist "%~1XIAOQI_CLAW_VERSION" exit /b 1
if not exist "%~1manager\server.js" exit /b 1
if not exist "%~1portable-license-public.pem" exit /b 1
exit /b 0

:already_latest
echo Current version %TO_VERSION% is already the latest version.
goto :success_pause

:unsupported_version
echo [FAILED] This BAT only upgrades %FROM_VERSION% to %TO_VERSION%.
echo Detected version: %CURRENT_VERSION%
goto :fail

:bad_args
echo Usage: this-file.bat [--drive E:\] [--check-only]
goto :fail

:root_not_found
echo [FAILED] No valid Xiaoqi Claw USB drive was found.
echo Ordinary disks and non-Xiaoqi USB drives are ignored. Insert the Xiaoqi Claw USB and retry.
goto :fail

:multiple_roots
echo [FAILED] Found %ROOT_COUNT% Xiaoqi Claw USB drives.
echo Use --drive E:\ to select the intended Xiaoqi Claw USB drive.
goto :fail

:temp_failed
echo [FAILED] Cannot create the update workspace in the Windows temp folder.
goto :fail

:stale_cache_failed
echo [FAILED] Cannot remove the older cached upgrade package from the Windows temp folder.
echo Close programs that may be using the old download, then run this BAT again.
goto :fail

:bootstrap_download_failed
echo [FAILED] Updater download failed. The USB was not changed. Check the network and run this BAT again.
goto :fail

:bootstrap_extract_failed
echo [FAILED] Cannot extract the independent updater. The USB was not changed.
goto :fail

:bootstrap_incomplete
echo [FAILED] The independent updater is incomplete. The USB was not changed.
goto :fail

:package_download_failed
echo [FAILED] Upgrade download failed. The USB was not changed. Run this BAT again to resume or retry.
goto :fail

:package_verify_failed
echo [FAILED] Package signature or file verification failed. The USB was not changed.
if exist "%PACKAGE%" del /f /q "%PACKAGE%" >nul 2>nul
goto :fail

:update_failed
echo [FAILED] Upgrade did not finish. The updater attempted an automatic rollback.
echo Keep this error window and contact support.
goto :fail

:check_passed
echo.
echo [CHECK PASSED] Detection, download, SHA-256, signature and file verification passed. USB was not changed.
echo Download cache: %WORK%

:success_pause
pause
exit /b 0

:fail
echo.
echo Operation stopped. Wait for disk activity to stop before unplugging the USB.
echo.
pause
exit /b 1
