@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.
echo    By installing URVault Server you agree that:
echo.
echo    1. Software is provided AS-IS, no warranty of any kind.
echo    2. URVault LLC is not liable for data loss or server failure.
echo    3. You are responsible for your server security and access control.
echo    4. Your files go to YOUR server -- URVault LLC receives nothing.
echo    5. Governing law: State of Delaware, USA.
echo.
echo    Full terms:     https://urvault.net/terms
echo    Privacy policy: https://urvault.net/privacy
echo.
set /p "TOS_ACCEPT=  Do you accept the Terms of Service? (yes/no): "
if /i not "!TOS_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] Setting up database...
set "MYSQL_WAS_FRESH=0"
set "MYSQL_FOUND=0"
set "MYSQL_SVC_BIN="

:: Scan common install paths (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"
    )
)

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

:: Check for existing MySQL service (installed but bin not in PATH)
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 (
        powershell -NoProfile -Command "$s=Get-WmiObject Win32_Service | Where-Object {$_.Name -like 'MySQL*'} | Select-Object -First 1; if($s){$p=$s.PathName.Trim([char]34); Split-Path $p -Parent}" > "%TEMP%\urvault_mysql_bin.txt" 2>nul
        set /p MYSQL_SVC_BIN=<"%TEMP%\urvault_mysql_bin.txt"
        if defined MYSQL_SVC_BIN (
            if exist "!MYSQL_SVC_BIN!\mysql.exe" (
                set "PATH=!PATH!;!MYSQL_SVC_BIN!"
                set "MYSQL_FOUND=1"
            )
        )
    )
)

:: Install via winget if MySQL not found at all
if "!MYSQL_FOUND!"=="0" (
    if "!WINGET_OK!"=="0" (
        echo.
        echo  ERROR: MySQL is not installed and winget is not available.
        echo  Please install MySQL 8.4 from https://dev.mysql.com/downloads/installer/
        echo  then re-run this installer.
        pause & exit /b 1
    )
    echo        Installing MySQL...
    winget install --id Oracle.MySQL -e --silent --accept-package-agreements --accept-source-agreements
    for /f "usebackq delims=" %%p in (`powershell -NoProfile -Command "[Environment]::GetEnvironmentVariable('PATH','Machine')"`) do (
        set "PATH=%%p;!PATH!"
    )
    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"
        )
    )
)

:: Initialize MySQL if no service exists (winget installs binaries only -- no service, no data dir)
powershell -NoProfile -Command "if (Get-Service 'MySQL*' -EA SilentlyContinue) { exit 0 } else { exit 1 }" >nul 2>&1
if !errorLevel! neq 0 (
    set "MYSQL_INIT_BIN="
    set "MYSQL_INIT_VER="
    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\mysqld.exe" (
            if not defined MYSQL_INIT_BIN (
                set "MYSQL_INIT_BIN=C:\Program Files\MySQL\MySQL Server %%v\bin"
                set "MYSQL_INIT_VER=%%v"
            )
        )
    )
    if defined MYSQL_INIT_BIN (
        echo        Initializing database ^(~15 seconds^)...
        if not exist "C:\ProgramData\MySQL\MySQL Server !MYSQL_INIT_VER!" mkdir "C:\ProgramData\MySQL\MySQL Server !MYSQL_INIT_VER!" >nul 2>&1
        if not exist "C:\ProgramData\MySQL\MySQL Server !MYSQL_INIT_VER!\Data" mkdir "C:\ProgramData\MySQL\MySQL Server !MYSQL_INIT_VER!\Data" >nul 2>&1
        set "MYSQL_INI=C:\ProgramData\MySQL\MySQL Server !MYSQL_INIT_VER!\my.ini"
        > "!MYSQL_INI!" (
            echo [mysqld]
            echo basedir=C:/Program Files/MySQL/MySQL Server !MYSQL_INIT_VER!/
            echo datadir=C:/ProgramData/MySQL/MySQL Server !MYSQL_INIT_VER!/Data
            echo port=3306
        )
        "!MYSQL_INIT_BIN!\mysqld.exe" "--defaults-file=!MYSQL_INI!" --initialize-insecure --console >nul 2>&1
        "!MYSQL_INIT_BIN!\mysqld.exe" "--defaults-file=!MYSQL_INI!" --install MySQL84 >nul 2>&1
        set "MYSQL_WAS_FRESH=1"
    )
)

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

:: Wait up to 60s for MySQL to accept connections on port 3306
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
        )
    )
)

:: Verify CLI available
mysql --version >nul 2>&1
if !errorLevel! neq 0 (
    echo.
    echo  ERROR: MySQL CLI not found after setup.
    echo  Please add the MySQL bin folder to PATH manually and re-run.
    pause & exit /b 1
)

:: Verify port is responding
if "!MYSQL_READY!"=="0" (
    echo.
    echo  ERROR: MySQL is not responding on port 3306.
    echo  Open Services ^(services.msc^) and ensure the MySQL service is Running,
    echo  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] Configuring database...
set "URVAULT_MYSQL_ROOT_PW="
set "URVAULT_STD_PW=URVaultSvr2026"

:: Attempt 1: blank password (fresh install with --initialize-insecure)
mysql -u root --password="" -e "SELECT 1;" >nul 2>&1
if !errorLevel! equ 0 (
    mysql -u root --password="" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '!URVAULT_STD_PW!'; FLUSH PRIVILEGES;" >nul 2>&1
    set "URVAULT_MYSQL_ROOT_PW=!URVAULT_STD_PW!"
    goto :mysql_auth_done
)

:: Attempt 2: our standard password (re-install scenario)
mysql -u root -p"!URVAULT_STD_PW!" -e "SELECT 1;" >nul 2>&1
if !errorLevel! equ 0 (
    set "URVAULT_MYSQL_ROOT_PW=!URVAULT_STD_PW!"
    goto :mysql_auth_done
)

:: Attempt 3: detect temp password from MySQL error log (MySQL installer sets one)
echo        Detecting credentials...
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) { foreach ($dd in ($d.FullName+'\Data'),$d.FullName) { $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 {}" > "%TEMP%\urvault_mysql_pw.txt" 2>nul
set "TEMP_PW="
set /p TEMP_PW=<"%TEMP%\urvault_mysql_pw.txt"
if defined TEMP_PW (
    mysql -u root -p"!TEMP_PW!" --connect-expired-password -e "SELECT 1;" >nul 2>&1
    if !errorLevel! equ 0 (
        mysql -u root -p"!TEMP_PW!" --connect-expired-password -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '!URVAULT_STD_PW!'; FLUSH PRIVILEGES;" >nul 2>&1
        set "URVAULT_MYSQL_ROOT_PW=!URVAULT_STD_PW!"
        goto :mysql_auth_done
    )
)

:: Attempt 4: silent auto-reset via --init-file (unknown existing password)
echo        Resetting credentials...
set "MYSQL_RESET_BIN="
powershell -NoProfile -Command "(Get-Command mysql -EA SilentlyContinue).Source | Split-Path -Parent" > "%TEMP%\urvault_mysql_dir.txt" 2>nul
set /p MYSQL_RESET_BIN=<"%TEMP%\urvault_mysql_dir.txt"
if not defined MYSQL_RESET_BIN if defined MYSQL_SVC_BIN set "MYSQL_RESET_BIN=!MYSQL_SVC_BIN!"
if not defined MYSQL_RESET_BIN (
    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\mysqld.exe" (
            if not defined MYSQL_RESET_BIN set "MYSQL_RESET_BIN=C:\Program Files\MySQL\MySQL Server %%v\bin"
        )
    )
)
if defined MYSQL_RESET_BIN (
    set "RESET_SQL=%TEMP%\urvault_mysql_reset.sql"
    echo ALTER USER 'root'@'localhost' IDENTIFIED BY '!URVAULT_STD_PW!';> "!RESET_SQL!"
    echo FLUSH PRIVILEGES;>> "!RESET_SQL!"
    powershell -NoProfile -Command "Stop-Service (Get-Service 'MySQL*' | Select-Object -First 1).Name -Force -EA SilentlyContinue" >nul 2>&1
    timeout /t 3 /nobreak >nul
    powershell -NoProfile -Command "$s=Get-WmiObject Win32_Service|Where-Object{$_.Name -like 'MySQL*'}|Select-Object -First 1; if($s.PathName -match '--defaults-file=""([^""]+)""'){$Matches[1]}" > "%TEMP%\urvault_defaults.txt" 2>nul
    set "MYSQL_DEFAULTS_FILE="
    set /p MYSQL_DEFAULTS_FILE=<"%TEMP%\urvault_defaults.txt"
    if defined MYSQL_DEFAULTS_FILE (
        start /b "" "!MYSQL_RESET_BIN!\mysqld.exe" "--defaults-file=!MYSQL_DEFAULTS_FILE!" "--init-file=!RESET_SQL!"
    ) else (
        start /b "" "!MYSQL_RESET_BIN!\mysqld.exe" "--init-file=!RESET_SQL!"
    )
    timeout /t 15 /nobreak >nul
    "!MYSQL_RESET_BIN!\mysqladmin.exe" -u root "-p!URVAULT_STD_PW!" shutdown >nul 2>&1
    timeout /t 4 /nobreak >nul
    taskkill /f /im mysqld.exe >nul 2>&1
    timeout /t 3 /nobreak >nul
    powershell -NoProfile -Command "Start-Service (Get-Service 'MySQL*' | Select-Object -First 1).Name -EA SilentlyContinue" >nul 2>&1
    timeout /t 5 /nobreak >nul
    mysql -u root -p"!URVAULT_STD_PW!" -e "SELECT 1;" >nul 2>&1
    if !errorLevel! equ 0 (
        set "URVAULT_MYSQL_ROOT_PW=!URVAULT_STD_PW!"
        goto :mysql_auth_done
    )
)

:: All automatic attempts failed
echo.
echo  ERROR: Could not configure MySQL automatically.
echo  Please contact support at support@urvault.net
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
