@echo off
setlocal EnableDelayedExpansion
title URVault Server Setup
color 0A

:: ── Self-elevate to Administrator ────────────────────────────────────────────
net session >nul 2>&1
if %errorLevel% neq 0 (
    echo.
    echo  Requesting administrator access...
    echo  Please click Yes on the UAC prompt. A new window will open for setup.
    echo.
    powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath cmd.exe -ArgumentList '/k \"\"%~f0\"\"' -Verb RunAs -WindowStyle Normal"
    exit /b
)

cd /d "%~dp0"

echo.
echo  ============================================================
echo    URVault Server Setup
echo  ============================================================
echo.

:: ── Terms of Service ──────────────────────────────────────────────────────────
echo  TERMS OF SERVICE
echo  ============================================================
echo  By installing URVault you agree that:
echo    - Software is provided AS IS with no warranty
echo    - URVault LLC is not liable for data loss or server failure
echo    - You are responsible for your server security
echo    - Governing law: State of Delaware, USA
echo.
echo  Full terms:     https://urvault.net/terms
echo  Privacy policy: https://urvault.net/privacy
echo.
set /p ACCEPT="  Do you accept the Terms of Service? (yes/no): "
if /i not "%ACCEPT%"=="yes" (
    echo.
    echo  Installation cancelled.
    pause
    exit /b 0
)
echo.
echo  Terms accepted. Starting installation -- please keep this window open.
echo  ============================================================
echo.

:: ── Check winget availability (may be absent on older Windows 10) ─────────────
set "WINGET_OK=0"
winget --version >nul 2>&1
if !errorLevel! equ 0 set "WINGET_OK=1"

:: ── [1/6] Node.js ─────────────────────────────────────────────────────────────
echo  [1/6] Node.js...
node --version >nul 2>&1
if %errorLevel% neq 0 (
    echo        Not found -- installing automatically...
    if "!WINGET_OK!"=="1" (
        winget install --id OpenJS.NodeJS.LTS -e --silent --accept-package-agreements --accept-source-agreements
    ) else (
        echo.
        echo  ERROR: winget not available on this system.
        echo  Please install Node.js manually from https://nodejs.org/
        echo  then re-run this installer.
        pause & exit /b 1
    )
    for /f "usebackq delims=" %%p in (`powershell -NoProfile -Command "[Environment]::GetEnvironmentVariable('PATH','Machine')"`) do (
        set "PATH=%%p;!PATH!"
    )
    node --version >nul 2>&1
    if !errorLevel! neq 0 (
        echo.
        echo  ERROR: Node.js install failed.
        echo  Download from https://nodejs.org/ then re-run this installer.
        pause & exit /b 1
    )
)
for /f %%v in ('node --version') do echo        %%v  OK

:: ── [2/6] MySQL ───────────────────────────────────────────────────────────────
echo  [2/6] MySQL...
set "MYSQL_WAS_FRESH=0"
set "MYSQL_FOUND=0"

:: Step 1: Scan common install paths first (catches installs not in PATH)
for %%v in (9.2 9.1 9.0 8.4 8.3 8.2 8.1 8.0 5.7) do (
    if exist "C:\Program Files\MySQL\MySQL Server %%v\bin\mysql.exe" (
        set "PATH=!PATH!;C:\Program Files\MySQL\MySQL Server %%v\bin"
    )
)

:: Step 2: Check CLI
mysql --version >nul 2>&1
if !errorLevel! equ 0 set "MYSQL_FOUND=1"

:: Step 3: If CLI still not found, check for an existing MySQL service
::         (installed but bin not in PATH — e.g. old version, custom install)
if "!MYSQL_FOUND!"=="0" (
    powershell -NoProfile -Command "if (Get-Service 'MySQL*' -EA SilentlyContinue) { exit 0 } else { exit 1 }" >nul 2>&1
    if !errorLevel! equ 0 (
        echo        Existing MySQL service found -- locating bin directory...
        for /f "usebackq delims=" %%b in (`powershell -NoProfile -Command ^
            "try { $s=Get-WmiObject Win32_Service -Filter \"Name LIKE 'MySQL%%'\" | Select-Object -First 1; if($s){ Split-Path ($s.PathName -replace '\"','') -Parent } } catch {}"`) do (
            if exist "%%b\mysql.exe" (
                set "PATH=!PATH!;%%b"
                set "MYSQL_FOUND=1"
                echo        Found at: %%b
            )
        )
    )
)

:: Step 4: Nothing found at all -- install via winget
if "!MYSQL_FOUND!"=="0" (
    echo        Not found -- installing...
    if "!WINGET_OK!"=="0" (
        echo.
        echo  ERROR: MySQL is not installed and winget is not available on this system.
        echo  Please install MySQL 8.4 from https://dev.mysql.com/downloads/installer/
        echo  then re-run this installer.
        pause & exit /b 1
    )
    winget install --id Oracle.MySQL -e --silent --accept-package-agreements --accept-source-agreements
    :: Refresh PATH from registry after install
    for /f "usebackq delims=" %%p in (`powershell -NoProfile -Command "[Environment]::GetEnvironmentVariable('PATH','Machine')"`) do (
        set "PATH=%%p;!PATH!"
    )
    :: Scan paths again after install
    for %%v in (9.2 9.1 9.0 8.4 8.3 8.2 8.1 8.0) do (
        if exist "C:\Program Files\MySQL\MySQL Server %%v\bin\mysql.exe" (
            set "PATH=!PATH!;C:\Program Files\MySQL\MySQL Server %%v\bin"
        )
    )
    set "MYSQL_WAS_FRESH=1"
)

:: Step 5: Start whichever MySQL service exists (new or existing)
powershell -NoProfile -Command "
    \$svc = Get-Service -Name 'MySQL*' -EA SilentlyContinue | Select-Object -First 1
    if (\$svc -and \$svc.Status -ne 'Running') { Start-Service \$svc.Name -EA SilentlyContinue }
" >nul 2>&1

:: Step 6: Wait up to 60s for MySQL to accept connections on port 3306
echo        Waiting for MySQL...
set "MYSQL_READY=0"
for /L %%i in (1,1,30) do (
    if "!MYSQL_READY!"=="0" (
        powershell -NoProfile -Command "try{$t=New-Object Net.Sockets.TcpClient;$t.Connect('127.0.0.1',3306);$t.Close();exit 0}catch{exit 1}" >nul 2>&1
        if !errorLevel! equ 0 (
            set "MYSQL_READY=1"
        ) else (
            timeout /t 2 /nobreak >nul
        )
    )
)

:: Step 7: Verify CLI available
mysql --version >nul 2>&1
if !errorLevel! neq 0 (
    echo.
    echo  ERROR: MySQL CLI not found after setup.
    echo  If an older version of MySQL is installed, its bin folder may not be in PATH.
    echo  Add it manually: C:\Program Files\MySQL\MySQL Server X.X\bin
    echo  then re-run this installer.
    pause & exit /b 1
)

:: Step 8: Verify port is responding
if "!MYSQL_READY!"=="0" (
    echo.
    echo  ERROR: MySQL is not responding on port 3306.
    echo.
    echo  This usually means an older MySQL installation is conflicting.
    echo  To resolve:
    echo    1. Open Services ^(services.msc^) and check all MySQL services
    echo    2. Ensure the MySQL service is Running
    echo    3. If multiple MySQL versions are installed, remove the old one
    echo       via Add/Remove Programs, then re-run this installer
    echo.
    pause & exit /b 1
)

if "!MYSQL_WAS_FRESH!"=="1" (
    echo        Installed OK
) else (
    echo        Found OK
)

:: ── [3/6] MySQL root credentials ──────────────────────────────────────────────
echo  [3/6] MySQL credentials...
set "URVAULT_MYSQL_ROOT_PW="

:: Try blank/socket first (works on many existing installs)
mysql -u root --password="" -e "SELECT 1;" >nul 2>&1
if %errorLevel% equ 0 (
    echo        Root access OK ^(no password^)
    set "URVAULT_MYSQL_ROOT_PW="
    goto :mysql_auth_done
)

:: Auto-detect temp password from MySQL error log
:: Search both ProgramData and Program Files layouts, all versions, newest first
echo        Detecting MySQL credentials...
for /f "usebackq delims=" %%t in (`powershell -NoProfile -Command ^
    "try { $roots = @('C:\ProgramData\MySQL','C:\Program Files\MySQL'); $found = $null; foreach ($root in $roots) { if (!(Test-Path $root)) { continue }; $dirs = Get-ChildItem $root -Directory -EA SilentlyContinue | Sort-Object Name -Descending; foreach ($d in $dirs) { $dataDirs = @( (Join-Path $d.FullName 'Data'), $d.FullName ); foreach ($dd in $dataDirs) { $f = Get-ChildItem $dd -Filter '*.err' -EA SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1; if ($f) { $m = Select-String -Path $f.FullName -Pattern 'temporary password is generated for root@localhost: (.+)$'; if ($m) { $found = $m.Matches[0].Groups[1].Value.Trim(); break } } }; if ($found) { break } }; if ($found) { break } }; if ($found) { $found } } catch {}"`) do (
    if not "%%t"=="" set "TEMP_PW=%%t"
)

if defined TEMP_PW (
    mysql -u root -p"!TEMP_PW!" --connect-expired-password -e "SELECT 1;" >nul 2>&1
    if !errorLevel! equ 0 (
        echo        Temporary password found -- resetting to installer password...
        set "NEW_ROOT_PW=URVlt%RANDOM%%RANDOM%Adm"
        mysql -u root -p"!TEMP_PW!" --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '!NEW_ROOT_PW!';" >nul 2>&1
        if !errorLevel! equ 0 (
            set "URVAULT_MYSQL_ROOT_PW=!NEW_ROOT_PW!"
            echo        MySQL password configured.
        ) else (
            set "URVAULT_MYSQL_ROOT_PW=!TEMP_PW!"
        )
        goto :mysql_auth_done
    )
)

:: Last resort — ask the user
echo.
echo  Could not detect MySQL root password automatically.
echo  If this is a fresh install, find it by running this in PowerShell:
echo.
echo    Get-ChildItem 'C:\ProgramData\MySQL','C:\Program Files\MySQL' ^
echo      -Recurse -Filter '*.err' ^| Select-String 'temporary password'
echo.
set /p "URVAULT_MYSQL_ROOT_PW=  MySQL root password: "
echo.
mysql -u root -p"!URVAULT_MYSQL_ROOT_PW!" -e "SELECT 1;" >nul 2>&1
if !errorLevel! neq 0 (
    :: Normal auth failed — try with --connect-expired-password in case it's a temp password
    mysql -u root -p"!URVAULT_MYSQL_ROOT_PW!" --connect-expired-password -e "SELECT 1;" >nul 2>&1
    if !errorLevel! equ 0 (
        echo        Password is expired -- resetting to installer password...
        set "NEW_ROOT_PW=URVlt%RANDOM%%RANDOM%Adm"
        mysql -u root -p"!URVAULT_MYSQL_ROOT_PW!" --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '!NEW_ROOT_PW!';" >nul 2>&1
        if !errorLevel! equ 0 (
            set "URVAULT_MYSQL_ROOT_PW=!NEW_ROOT_PW!"
            echo        MySQL password reset successfully.
        )
    ) else (
        echo.
        echo  ERROR: Could not authenticate to MySQL with that password.
        echo.
        echo  If MySQL was installed previously and you do not remember the
        echo  root password, you can reset it:
        echo.
        echo    1. Open Services (services.msc) and stop the MySQL service
        echo    2. Open PowerShell as Administrator and run:
        echo         net stop MySQL84
        echo         mysqld --init-file="%TEMP%\mysql-reset.sql" --console
        echo       (where mysql-reset.sql contains:)
        echo         ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword1!';
        echo    3. Stop mysqld, restart MySQL service, then re-run this installer
        echo.
        echo  For full instructions search: "reset MySQL root password Windows"
        echo.
        pause & exit /b 1
    )
)

:mysql_auth_done
echo        OK

:: ── [4/6] Install Node.js dependencies ────────────────────────────────────────
echo  [4/6] Installing dependencies...
npm install --omit=dev
if %errorLevel% neq 0 (
    echo  WARNING: npm install reported errors. Continuing...
)

:: ── [5/6] Configure and install URVault ───────────────────────────────────────
echo  [5/6] Configuring URVault...
echo.
node install/auto-installer.js --auto
if %errorLevel% neq 0 (
    echo.
    echo  ERROR: Setup failed. See details above.
    pause & exit /b 1
)

:: ── Firewall rule ──────────────────────────────────────────────────────────────
echo        Configuring firewall...
netsh advfirewall firewall delete rule name="URVault Server" >nul 2>&1
netsh advfirewall firewall add rule name="URVault Server" dir=in action=allow protocol=TCP localport=5173 >nul 2>&1
echo        Firewall rule added ^(port 5173^)

:: ── [6/6] Windows service (auto-start on boot) ────────────────────────────────
echo.
echo  [6/6] Installing Windows service...

if not exist nssm.exe (
    echo        Downloading service manager...
    powershell -NoProfile -ExecutionPolicy Bypass -Command ^
        "try { Invoke-WebRequest -Uri 'https://nssm.cc/release/nssm-2.24.zip' -OutFile $env:TEMP\nssm.zip -TimeoutSec 30; Expand-Archive $env:TEMP\nssm.zip -DestinationPath $env:TEMP\nssm_extract -Force; Copy-Item $env:TEMP\nssm_extract\nssm-2.24\win64\nssm.exe . ; Remove-Item $env:TEMP\nssm.zip,$env:TEMP\nssm_extract -Recurse -Force; Write-Host '       nssm OK' } catch { Write-Host '       nssm download failed -- using task scheduler fallback' }" 2>&1
)

if exist nssm.exe (
    nssm stop URVaultServer >nul 2>&1
    nssm remove URVaultServer confirm >nul 2>&1
    nssm install URVaultServer "%SystemRoot%\System32\cmd.exe"
    nssm set URVaultServer AppParameters "/c \"%~dp0start-server.bat\" >> \"%~dp0server.log\" 2>&1"
    nssm set URVaultServer AppDirectory "%~dp0"
    nssm set URVaultServer DisplayName "URVault Server"
    nssm set URVaultServer Description "URVault personal cloud backup server"
    nssm set URVaultServer Start SERVICE_AUTO_START
    nssm start URVaultServer >nul 2>&1
    echo        Service installed and started ^(auto-starts on boot^)
) else (
    schtasks /delete /tn "URVaultServer" /f >nul 2>&1
    schtasks /create /f /tn "URVaultServer" /sc ONSTART /rl HIGHEST /ru SYSTEM ^
        /tr "cmd /c cd /d \"%~dp0\" && start-server.bat >> server.log 2>&1" /delay 0000:30 >nul 2>&1
    if !errorLevel! equ 0 (
        schtasks /run /tn "URVaultServer" >nul 2>&1
        echo        Scheduled task created ^(starts on boot^)
    ) else (
        echo        Could not install service. Start manually: double-click start-server.bat
    )
)

:: ── Done ──────────────────────────────────────────────────────────────────────
echo.
echo  ============================================================
echo    Setup Complete!
echo  ============================================================
echo.
echo    Open your browser to finish setup:
echo.
echo      http://localhost:5173
echo.
echo    Then pair your phone using the URVault app.
echo.
echo    The server starts automatically on boot.
echo    To start it now if not already running:
echo      double-click start-server.bat
echo.
pause
