@echo off
setlocal EnableDelayedExpansion

:: ============================================================================
:: iWinNAC Install / Upgrade (v0.0.4.6+)
:: Per-kiosk TLS certificate - no shared localhost.pfx required
:: Must be run as Administrator
:: ============================================================================

set PORT=12030
set BIND_IP=127.0.0.1
set BIND_IP6=[::1]
set APPID={00000000-0000-0000-1111-AABBCCDDEEFF}
set LEGACY_THUMB=F3C26347A7224962CF5E37BBE70831FEDDEE63B
set IKCS_WAIT_SEC=90
set SERVICE_WAIT_SEC=90
set SERVICE_STOP_WAIT_SEC=30
set MSI_WAIT_SEC=120
set MSI_ESTIMATE_SEC=60
set SERVICE_NAME=Integra WinNAC
set PRODUCT_GUID={98AC1AFD-FBE9-40F4-A8D6-8D665EB2BE61}
set HTTPS_RETRY_COUNT=5
set HTTPS_RETRY_DELAY=3
set "LOG_FILE=%~dp0iWinNAC_install.log"
set "CERT_HELPER=%~dp0iWinNAC-CertHelper.ps1"
set "WAIT_HELPER=%~dp0iWinNAC-WaitHelper.ps1"
set "THUMB_FILE=%~dp0iWinNAC_thumb.txt"
set "META_FILE=%~dp0iWinNAC_cert_meta.txt"
set "ERR_FILE=%~dp0iWinNAC_last_error.txt"
set "MSI_FILE=%~dp0iWinNACSetup.msi"
set "VERIFY_OK=0"
set "VERIFY_WARN=0"

call :InitLog
call :InitRollbackState

:: --- Pre-checks ---
net session >nul 2>&1
if errorlevel 1 (
    call :PrepareFail "Administrator privileges required" "This script must be run as Administrator." "Right-click Run.bat and select 'Run as administrator'."
    goto :FailAndStop
)

if not exist "%CERT_HELPER%" (
    call :PrepareFail "Missing certificate helper script" "File not found: %CERT_HELPER%" "Ensure iWinNAC-CertHelper.ps1 is in the same folder as Run.bat."
    goto :FailAndStop
)

if not exist "%WAIT_HELPER%" (
    call :PrepareFail "Missing wait helper script" "File not found: %WAIT_HELPER%" "Ensure iWinNAC-WaitHelper.ps1 is in the same folder as Run.bat."
    goto :FailAndStop
)

if not exist "%MSI_FILE%" (
    call :PrepareFail "Missing MSI installer" "File not found: %MSI_FILE%" "Ensure iWinNACSetup.msi is in the same folder as Run.bat."
    goto :FailAndStop
)

where powershell >nul 2>&1
if errorlevel 1 (
    call :PrepareFail "PowerShell not available" "PowerShell is required for certificate generation." "Install Windows PowerShell 5.1 or later and run again."
    goto :FailAndStop
)

if exist "%ProgramFiles(x86)%\Integra\iWinNAC\" set "RB_MSI_FOLDER_EXISTS=1"
if exist "%ProgramFiles%\Integra\iWinNAC\" set "RB_MSI_FOLDER_EXISTS=1"
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\%PRODUCT_GUID%" >nul 2>&1
if not errorlevel 1 set "RB_MSI_WAS_INSTALLED=1"
reg query "HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\%PRODUCT_GUID%" >nul 2>&1
if not errorlevel 1 set "RB_MSI_WAS_INSTALLED=1"

:: --- Step 1: Stop service ---
echo [1/8] Stopping Integra WinNAC service...
call :LogStep "[1/8] Stopping Integra WinNAC service"
sc query "Integra WinNAC" >nul 2>&1
if errorlevel 1 (
    call :LogMsg "Service 'Integra WinNAC' is not installed yet. Continuing..."
) else (
    sc query "Integra WinNAC" | find /i "RUNNING" >nul 2>&1
    if not errorlevel 1 set "RB_SERVICE_WAS_RUNNING=1"
    sc stop "Integra WinNAC" >> "%LOG_FILE%" 2>&1
    if errorlevel 1 (
        call :LogMsg "WARNING: Could not stop service. It may already be stopped. Continuing..."
    )
    call :WaitForServiceStopped "Integra WinNAC" !SERVICE_STOP_WAIT_SEC! "Stopping service"
    if errorlevel 1 (
        call :LogMsg "WARNING: Service did not reach STOPPED within !SERVICE_STOP_WAIT_SEC! seconds. Continuing..."
    )
)
echo        Done.
echo.

:: --- Step 2: Remove old SSL bindings ---
echo [2/8] Removing previous HTTP.SYS SSL bindings...
call :LogStep "[2/8] Removing previous HTTP.SYS SSL bindings"
call :CaptureSslBinding
call :RemoveSslBindings
echo        Done.
echo.

:: --- Step 3: Create or reuse certificate ---
echo [3/8] Creating or reusing per-kiosk certificate...
call :LogStep "[3/8] Creating or reusing per-kiosk certificate"
set THUMB=
if exist "%THUMB_FILE%" del /f /q "%THUMB_FILE%" >nul 2>&1
if exist "%META_FILE%" del /f /q "%META_FILE%" >nul 2>&1
if exist "%ERR_FILE%" del /f /q "%ERR_FILE%" >nul 2>&1

echo        Please wait, this may take up to 30 seconds...
powershell -NoProfile -ExecutionPolicy Bypass -File "%CERT_HELPER%" -Action Ensure -OutputFile "%THUMB_FILE%" -OutputMetaFile "%META_FILE%" 2> "%ERR_FILE%"
set PS_ERR=!errorlevel!

if !PS_ERR! neq 0 (
    call :ShowCertErrors
    call :PrepareFail "Certificate creation failed" "PowerShell returned error code !PS_ERR!." "Review the error details above and iWinNAC_install.log. Ensure you are running as Administrator."
    goto :FailAndStop
)

call :ReadThumbprint
if errorlevel 1 (
    call :ShowCertErrors
    call :PrepareFail "Empty certificate thumbprint" "No valid thumbprint was returned after certificate creation." "Check iWinNAC_install.log and iWinNAC_last_error.txt, then run again as Administrator."
    goto :FailAndStop
)

call :ReadCertMeta
set "RB_CERT_THUMB=!THUMB!"

echo        [OK] Certificate ready.
call :LogMsg "Certificate thumbprint: !THUMB! (mode: !RB_CERT_MODE!)"
echo.

:: --- Step 4: Trust certificate ---
echo [4/8] Trusting certificate for local browser access...
call :LogStep "[4/8] Trusting certificate for local browser access"
if exist "%ERR_FILE%" del /f /q "%ERR_FILE%" >nul 2>&1

powershell -NoProfile -ExecutionPolicy Bypass -File "%CERT_HELPER%" -Action Trust -Thumbprint "!THUMB!" 1>> "%LOG_FILE%" 2> "%ERR_FILE%"
set PS_ERR=!errorlevel!

if !PS_ERR! neq 0 (
    call :ShowCertErrors
    call :PrepareFail "Certificate trust installation failed" "Could not add certificate to LocalMachine\Root store." "Run as Administrator. Verify thumbprint !THUMB! exists in certmgr.msc under Local Computer ^> Personal."
    goto :FailAndStop
)

set "RB_CERT_TRUSTED=1"
echo        [OK] Certificate trusted for browser access.
echo.

:: --- Step 5: SSL binding ---
echo [5/8] Binding certificate to loopback %BIND_IP%:%PORT% and %BIND_IP6%:%PORT%...
call :LogStep "[5/8] Binding certificate to loopback %BIND_IP%:%PORT% and %BIND_IP6%:%PORT%"
call :ApplySslBindings "!THUMB!"
if errorlevel 1 (
    call :PrepareFail "HTTP.SYS SSL binding failed" "netsh could not bind certificate to loopback port %PORT%." "Confirm thumbprint !THUMB! is in Local Computer ^> Personal. Run 'netsh http show sslcert' and retry as Administrator."
    goto :FailAndStop
)

set "RB_SSL_BOUND=1"
echo        [OK] SSL binding configured.
echo.

:: --- Step 6: MSI install ---
echo [6/8] Installing / upgrading iWinNAC MSI...
call :LogStep "[6/8] Installing / upgrading iWinNAC MSI"

::if "!RB_MSI_WAS_INSTALLED!"=="1" (
::    echo Removing previous version... >> "%LOG_FILE%"
::    start /wait msiexec /x "%MSI_FILE%" /qn /L*v "%~dp0iWinNAC_msi_uninstall.log"
::    set "RB_MSI_UNINSTALLED=1"
::)

msiexec /x {98AC1AFD-FBE9-40F4-A8D6-8D665EB2BE61} /qn /L*v "%~dp0iWinNAC_msi_uninstall.log"
set "RB_MSI_UNINSTALLED=1"

echo Installing iWinNAC... >> "%LOG_FILE%"
start "" /min msiexec /i "%MSI_FILE%" /qn /L*v "%~dp0iWinNAC_msi_install.log"
call :WaitForMsiInstall "Installing iWinNAC MSI"
if errorlevel 1 (
    call :ResolveProgramPath
    if not "!ProgramPath!"=="" call :EnsureWinNacServiceRegistered
    sc query "%SERVICE_NAME%" >nul 2>&1
    if errorlevel 1 (
        call :PrepareFail "MSI installation failed" "iWinNAC MSI finished but '%SERVICE_NAME%' service was not registered." "Check iWinNAC_msi_install.log and iWinNAC_installutil.log. Ensure .NET Framework 4.x is installed."
        goto :FailAndStop
    )
    call :LogMsg "WARNING: MSI wait timed out but service registration was detected. Continuing..."
)

set "RB_MSI_INSTALLED=1"
echo        [OK] MSI installation completed.
echo        MSI log: %~dp0iWinNAC_msi_install.log
echo.
call :ProgressDelay 3 "Finalizing MSI installation"
echo.

:: --- Step 7: Post-install configuration ---
echo [7/8] Configuring service and assets...
call :LogStep "[7/8] Configuring service and assets"
call :ResolveProgramPath

if "!ProgramPath!"=="" (
    call :PrepareFail "Installation folder not found" "MSI install folder not found in either location: '%ProgramFiles(x86)%\Integra\iWinNAC' or '%ProgramFiles%\Integra\iWinNAC'." "Check iWinNAC_install.log for MSI errors. Confirm iWinNACSetup.msi installed successfully, then re-run Run.bat."
    goto :FailAndStop
)

call :LogMsg "Program path: !ProgramPath!"

if exist "%~dp0*.bmp" (
    call :CopyBmpFiles "!ProgramPath!"
)

call :ConfigureServiceRecovery
call :DisableFastStartup

echo        [OK] Service configuration completed.
echo        Install path: !ProgramPath!
echo.

:: --- Step 8: Start service ---
echo [8/8] Starting Integra WinNAC service...
call :LogStep "[8/8] Starting Integra WinNAC service"

sc query "%SERVICE_NAME%" >nul 2>&1
if errorlevel 1 (
    call :EnsureWinNacServiceRegistered
    if errorlevel 1 (
        call :PrepareFail "Service not registered" "Windows service '%SERVICE_NAME%' was not found after MSI installation." "Check iWinNAC_msi_install.log and iWinNAC_installutil.log, then re-run Run.bat as Administrator."
        goto :FailAndStop
    )
)

sc query "%SERVICE_NAME%" | find /i "RUNNING" >nul 2>&1
if errorlevel 1 (
    sc start "Integra WinNAC" >> "%LOG_FILE%" 2>&1
    if errorlevel 1 (
        sc query "Integra WinNAC" | find /i "RUNNING" >nul 2>&1
        if errorlevel 1 (
            sc query "Integra WinNAC" | find /i "START_PENDING" >nul 2>&1
            if errorlevel 1 (
                call :PrepareFail "Service start failed" "Could not start 'Integra WinNAC' service." "Open services.msc, check Integra WinNAC status and Windows Event Viewer. Review iWinNAC_msi_install.log."
                goto :FailAndStop
            )
        )
    )
) else (
    call :LogMsg "Service was already RUNNING after MSI install."
)

call :WaitForServiceRunning "Integra WinNAC" !SERVICE_WAIT_SEC! "Starting Integra WinNAC service"
if errorlevel 1 (
    sc query "Integra WinNAC" | find /i "RUNNING" >nul 2>&1
    if errorlevel 1 (
        call :PrepareFail "Service not running" "Integra WinNAC did not reach RUNNING state within !SERVICE_WAIT_SEC! seconds." "Open services.msc and check service status. Ensure a user is logged in and iKCS.exe is not blocked by antivirus."
        goto :FailAndStop
    )
)

set "RB_SERVICE_STARTED=1"
echo        [OK] Integra WinNAC service is RUNNING.
echo.
echo Waiting for iKCS.exe to start (up to !IKCS_WAIT_SEC! seconds)...
call :WaitForProcessStart "iKCS.exe" !IKCS_WAIT_SEC! "Starting iKCS.exe (HTTPS host)"
set IKCS_READY=!errorlevel!

if !IKCS_READY! equ 0 (
    echo        [OK] iKCS.exe is running.
    call :ProgressDelay 5 "Initializing HTTPS listener"
) else (
    echo        [WARN] iKCS.exe was not detected yet. HTTPS test may fail.
    echo               Ensure a user is logged in to the kiosk session.
)
echo.

:: --- Verification ---
call :RunVerification

echo.
echo ============================================================
echo   INSTALLATION COMPLETE
echo ============================================================
echo   Log file            : %LOG_FILE%
echo ============================================================
echo.
if !VERIFY_WARN! gtr 0 (
    echo NOTE: Items marked [WARN] above are informational.
    echo       Test https://localhost:%PORT%/service/GetAppVersion in the browser.
    echo       For Test_Sample buttons, run OpenTestPage.bat - do not open
    echo       TestPage.html directly from Explorer; file URLs are blocked by browsers.
    echo.
)
pause
exit /b 0

:: ============================================================================
:: Subroutines
:: ============================================================================

:InitLog
echo ============================================================ > "%LOG_FILE%"
echo iWinNAC installation started: %DATE% %TIME% >> "%LOG_FILE%"
echo Computer: %COMPUTERNAME% >> "%LOG_FILE%"
echo Working folder: %~dp0 >> "%LOG_FILE%"
echo ============================================================ >> "%LOG_FILE%"
goto :eof

:InitRollbackState
set "RB_SSL_BOUND=0"
set "RB_CERT_TRUSTED=0"
set "RB_CERT_NEW=0"
set "RB_CERT_MODE=UNKNOWN"
set "RB_CERT_THUMB="
set "RB_MSI_WAS_INSTALLED=0"
set "RB_MSI_UNINSTALLED=0"
set "RB_MSI_INSTALLED=0"
set "RB_SERVICE_WAS_RUNNING=0"
set "RB_SERVICE_STARTED=0"
set "RB_OLD_SSL_THUMB="
set "RB_OLD_SSL_IP="
goto :eof

:CaptureSslBinding
for /f "usebackq delims=" %%H in (`powershell -NoProfile -Command "$out = netsh http show sslcert ipport=%BIND_IP%:%PORT% 2>$null; if ($out -match 'Hash\s*:\s*([a-fA-F0-9]+)') { $matches[1] }"`) do set "RB_OLD_SSL_THUMB=%%H"
if defined RB_OLD_SSL_THUMB (
    set "RB_OLD_SSL_IP=%BIND_IP%"
    call :LogMsg "Saved previous SSL binding: %BIND_IP%:%PORT% thumbprint !RB_OLD_SSL_THUMB!"
    goto :eof
)
for /f "usebackq delims=" %%H in (`powershell -NoProfile -Command "$out = netsh http show sslcert ipport=0.0.0.0:%PORT% 2>$null; if ($out -match 'Hash\s*:\s*([a-fA-F0-9]+)') { $matches[1] }"`) do set "RB_OLD_SSL_THUMB=%%H"
if defined RB_OLD_SSL_THUMB (
    set "RB_OLD_SSL_IP=0.0.0.0"
    call :LogMsg "Saved previous SSL binding: 0.0.0.0:%PORT% thumbprint !RB_OLD_SSL_THUMB!"
    goto :eof
)
for /f "usebackq delims=" %%H in (`powershell -NoProfile -Command "$out = netsh http show sslcert ipport=%BIND_IP6%:%PORT% 2>$null; if ($out -match 'Hash\s*:\s*([a-fA-F0-9]+)') { $matches[1] }"`) do set "RB_OLD_SSL_THUMB=%%H"
if defined RB_OLD_SSL_THUMB (
    set "RB_OLD_SSL_IP=%BIND_IP6%"
    call :LogMsg "Saved previous SSL binding: %BIND_IP6%:%PORT% thumbprint !RB_OLD_SSL_THUMB!"
)
goto :eof

:RemoveSslBindings
netsh http delete sslcert ipport=0.0.0.0:%PORT% >> "%LOG_FILE%" 2>&1
netsh http delete sslcert ipport=%BIND_IP%:%PORT% >> "%LOG_FILE%" 2>&1
netsh http delete sslcert ipport=%BIND_IP6%:%PORT% >> "%LOG_FILE%" 2>&1
goto :eof

:ApplySslBindings
set "_SSL_THUMB=%~1"
netsh http add sslcert ipport=%BIND_IP%:%PORT% certhash=!_SSL_THUMB! appid=%APPID% >> "%LOG_FILE%" 2>&1
if errorlevel 1 exit /b 1
netsh http add sslcert ipport=%BIND_IP6%:%PORT% certhash=!_SSL_THUMB! appid=%APPID% >> "%LOG_FILE%" 2>&1
if errorlevel 1 (
    call :LogMsg "WARNING: Could not bind SSL certificate on %BIND_IP6%:%PORT%. IPv4 loopback binding is active."
)
exit /b 0

:LogStep
echo %~1 >> "%LOG_FILE%"
goto :eof

:LogMsg
echo %~1 >> "%LOG_FILE%"
goto :eof

:ReadThumbprint
set "THUMB="
if not exist "%THUMB_FILE%" exit /b 1
for /f "usebackq delims=" %%T in ("%THUMB_FILE%") do set "THUMB=%%T"
if exist "%THUMB_FILE%" del /f /q "%THUMB_FILE%" >nul 2>&1
set "THUMB=!THUMB: =!"
if "!THUMB!"=="" exit /b 1
exit /b 0

:ReadCertMeta
set "RB_CERT_MODE=UNKNOWN"
set "RB_CERT_NEW=0"
if not exist "%META_FILE%" goto :eof
for /f "usebackq delims=" %%M in ("%META_FILE%") do set "RB_CERT_MODE=%%M"
if exist "%META_FILE%" del /f /q "%META_FILE%" >nul 2>&1
if /i "!RB_CERT_MODE!"=="NEW" set "RB_CERT_NEW=1"
goto :eof

:PrepareFail
set "FAIL_TITLE=%~1"
set "FAIL_REASON=%~2"
set "FAIL_ACTION=%~3"
goto :eof

:ProgressDelay
powershell -NoProfile -ExecutionPolicy Bypass -File "%WAIT_HELPER%" -Action ProgressDelay -Label "%~2" -MaxSeconds %~1 -SleepSeconds 1
goto :eof

:WaitForProcessEnd
powershell -NoProfile -ExecutionPolicy Bypass -File "%WAIT_HELPER%" -Action WaitProcessEnd -ProcessName "%~1" -Label "%~3" -MaxSeconds %~2 -SleepSeconds 1
exit /b %errorlevel%

:WaitForMsiInstall
powershell -NoProfile -ExecutionPolicy Bypass -File "%WAIT_HELPER%" -Action WaitMsiInstall -Label "%~1" -MaxSeconds !MSI_WAIT_SEC! -EstimatedSeconds !MSI_ESTIMATE_SEC! -SleepSeconds 1 -InstallPathsList "%ProgramFiles(x86)%\Integra\iWinNAC;%ProgramFiles%\Integra\iWinNAC" -ServiceName "%SERVICE_NAME%"
exit /b %errorlevel%

:ResolveProgramPath
set "ProgramPath="
if exist "%ProgramFiles(x86)%\Integra\iWinNAC\" (
    set "ProgramPath=%ProgramFiles(x86)%\Integra\iWinNAC"
) else if exist "%ProgramFiles%\Integra\iWinNAC\" (
    set "ProgramPath=%ProgramFiles%\Integra\iWinNAC"
)
goto :eof

:EnsureWinNacServiceRegistered
sc query "%SERVICE_NAME%" >nul 2>&1
if not errorlevel 1 exit /b 0

if "!ProgramPath!"=="" call :ResolveProgramPath
if "!ProgramPath!"=="" exit /b 1
if not exist "!ProgramPath!\iWinNAC.exe" exit /b 1

call :LogMsg "Attempting service registration via InstallUtil for !ProgramPath!\iWinNAC.exe"

set "_INSTALLUTIL="
if exist "%WINDIR%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe" set "_INSTALLUTIL=%WINDIR%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe"
if "!_INSTALLUTIL!"=="" (
    call :LogMsg "ERROR: InstallUtil.exe not found under %WINDIR%\Microsoft.NET\Framework\v4.0.30319\"
    exit /b 1
)

"!_INSTALLUTIL!" /LogFile="%~dp0iWinNAC_installutil.log" "!ProgramPath!\iWinNAC.exe" >> "%LOG_FILE%" 2>&1
sc query "%SERVICE_NAME%" >nul 2>&1
exit /b %errorlevel%

:CopyBmpFiles
set "_DEST=%~1"
for %%F in ("%~dp0*.bmp") do (
    copy /Y "%%F" "!_DEST!\" >nul 2>&1
    if errorlevel 1 (
        call :LogMsg "WARNING: Failed to copy %%~nxF. Retrying..."
        timeout /t 2 /nobreak >nul
        copy /Y "%%F" "!_DEST!\" >> "%LOG_FILE%" 2>&1
        if errorlevel 1 call :LogMsg "WARNING: Could not copy %%~nxF. Continuing..."
    )
)
goto :eof

:ConfigureServiceRecovery
sc failure "Integra WinNAC" reset=0 actions= restart/60000/restart/60000/restart/60000 >nul 2>&1
if errorlevel 1 call :LogMsg "WARNING: Failed to configure service recovery options."
goto :eof

:DisableFastStartup
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power" /v HiberbootEnabled /t reg_dword /d 0 /f >nul 2>&1
if errorlevel 1 call :LogMsg "WARNING: Failed to disable fast startup registry setting."
goto :eof

:WaitForServiceStopped
powershell -NoProfile -ExecutionPolicy Bypass -File "%WAIT_HELPER%" -Action WaitServiceStopped -ServiceName "%~1" -Label "%~3" -MaxSeconds %~2 -SleepSeconds 1
exit /b %errorlevel%

:WaitForServiceRunning
powershell -NoProfile -ExecutionPolicy Bypass -File "%WAIT_HELPER%" -Action WaitService -ServiceName "%~1" -Label "%~3" -MaxSeconds %~2 -SleepSeconds 1
exit /b %errorlevel%

:WaitForProcessStart
powershell -NoProfile -ExecutionPolicy Bypass -File "%WAIT_HELPER%" -Action WaitProcessStart -ProcessName "%~1" -Label "%~3" -MaxSeconds %~2 -SleepSeconds 2
exit /b %errorlevel%

:RunVerification
echo ============================================================
echo   VERIFICATION SUMMARY
echo ============================================================
set "VERIFY_OK=0"
set "VERIFY_WARN=0"

netsh http show sslcert ipport=%BIND_IP%:%PORT% >> "%LOG_FILE%" 2>&1
netsh http show sslcert ipport=%BIND_IP6%:%PORT% >> "%LOG_FILE%" 2>&1
netsh http show sslcert ipport=%BIND_IP%:%PORT% 2>nul | find /i "!THUMB!" >nul 2>&1
if errorlevel 1 (
    echo   [WARN] HTTPS certificate binding could not be verified on %BIND_IP%:%PORT%
    set /a VERIFY_WARN+=1
) else (
    echo   [OK]   HTTPS certificate bound on %BIND_IP%:%PORT%
    set /a VERIFY_OK+=1
)
netsh http show sslcert ipport=%BIND_IP6%:%PORT% 2>nul | find /i "!THUMB!" >nul 2>&1
if errorlevel 1 (
    echo   [WARN] HTTPS certificate binding could not be verified on %BIND_IP6%:%PORT%
    set /a VERIFY_WARN+=1
) else (
    echo   [OK]   HTTPS certificate bound on %BIND_IP6%:%PORT%
    set /a VERIFY_OK+=1
)

sc query "Integra WinNAC" | find /i "RUNNING" >nul
if errorlevel 1 (
    echo   [WARN] Integra WinNAC service is not RUNNING
    set /a VERIFY_WARN+=1
) else (
    echo   [OK]   Integra WinNAC service is RUNNING
    set /a VERIFY_OK+=1
)

tasklist /FI "IMAGENAME eq iKCS.exe" 2>nul | find /I "iKCS.exe" >nul
if errorlevel 1 (
    echo   [WARN] iKCS.exe process not detected
    echo          ^> Log in to the kiosk user session if this is a fresh install
    set /a VERIFY_WARN+=1
) else (
    echo   [OK]   iKCS.exe process is running
    set /a VERIFY_OK+=1
)

echo   Testing HTTPS endpoint (up to !HTTPS_RETRY_COUNT! attempts)...
set "HTTPS_OK=0"
for /L %%R in (1,1,!HTTPS_RETRY_COUNT!) do (
    if "!HTTPS_OK!"=="0" (
        powershell -NoProfile -ExecutionPolicy Bypass -Command "try { $r = Invoke-WebRequest -Uri 'https://localhost:%PORT%/service/GetAppVersion' -UseBasicParsing -TimeoutSec 10; if ($r.StatusCode -ge 200) { exit 0 } else { exit 1 } } catch { exit 1 }" >nul 2>&1
        if !errorlevel! equ 0 set "HTTPS_OK=1"
        if "!HTTPS_OK!"=="0" timeout /t !HTTPS_RETRY_DELAY! /nobreak >nul
    )
)
echo.

if "!HTTPS_OK!"=="1" (
    echo   [OK]   HTTPS endpoint responded at https://localhost:%PORT%/service/GetAppVersion
    set /a VERIFY_OK+=1
) else (
    echo   [WARN] HTTPS test from this script did not get a response
    echo          ^> This is NOT an installation failure if the service is RUNNING
    echo          ^> Test manually in browser: https://localhost:%PORT%/service/GetAppVersion
    set /a VERIFY_WARN+=1
)

echo ============================================================
echo   Result: !VERIFY_OK! passed, !VERIFY_WARN! warning(s)
echo ============================================================
call :LogMsg "Verification: !VERIFY_OK! passed, !VERIFY_WARN! warning(s)"
goto :eof

:ShowCertErrors
echo.
if exist "%ERR_FILE%" (
    echo --- Certificate script error details ---
    type "%ERR_FILE%"
    echo ----------------------------------------
    type "%ERR_FILE%" >> "%LOG_FILE%"
)
goto :eof

:Rollback
echo.
echo ============================================================
echo   ROLLBACK IN PROGRESS
echo ============================================================
echo   Reverting changes made during this failed installation...
echo.
call :LogMsg "Rollback started"

if "!RB_SERVICE_STARTED!"=="1" (
    echo   - Stopping Integra WinNAC service...
    sc stop "Integra WinNAC" >> "%LOG_FILE%" 2>&1
    call :LogMsg "Rollback: stopped service"
)

if "!RB_MSI_INSTALLED!"=="1" (
    echo   - Uninstalling iWinNAC MSI installed in this run...
    start /wait msiexec /x "%MSI_FILE%" /qn /L*v "%~dp0iWinNAC_msi_uninstall.log"
    call :LogMsg "Rollback: MSI uninstalled"
)

if "!RB_SSL_BOUND!"=="1" (
    echo   - Removing SSL bindings on loopback port %PORT%...
    call :RemoveSslBindings
    call :LogMsg "Rollback: SSL bindings removed"
)

if not "!RB_OLD_SSL_THUMB!"=="" (
    echo   - Restoring previous SSL binding on !RB_OLD_SSL_IP!:%PORT%...
    netsh http add sslcert ipport=!RB_OLD_SSL_IP!:%PORT% certhash=!RB_OLD_SSL_THUMB! appid=%APPID% >> "%LOG_FILE%" 2>&1
    call :LogMsg "Rollback: previous SSL binding restored"
)

if "!RB_CERT_NEW!"=="1" if not "!RB_CERT_THUMB!"=="" (
    echo   - Removing newly created certificate...
    powershell -NoProfile -ExecutionPolicy Bypass -File "%CERT_HELPER%" -Action Remove -Thumbprint "!RB_CERT_THUMB!" >> "%LOG_FILE%" 2>&1
    call :LogMsg "Rollback: new certificate removed"
) else if "!RB_CERT_TRUSTED!"=="1" if not "!RB_CERT_THUMB!"=="" (
    echo   - Removing certificate trust added in this run...
    powershell -NoProfile -ExecutionPolicy Bypass -File "%CERT_HELPER%" -Action RemoveTrust -Thumbprint "!RB_CERT_THUMB!" >> "%LOG_FILE%" 2>&1
    call :LogMsg "Rollback: certificate trust removed"
)

if "!RB_MSI_UNINSTALLED!"=="1" if "!RB_MSI_WAS_INSTALLED!"=="1" if not "!RB_MSI_INSTALLED!"=="1" (
    echo   - Restoring previous iWinNAC MSI installation...
    start /wait msiexec /i "%MSI_FILE%" /qn /L*v "%~dp0iWinNAC_msi_install.log"
    call :LogMsg "Rollback: previous MSI restored"
)

if "!RB_SERVICE_WAS_RUNNING!"=="1" (
    sc query "Integra WinNAC" >nul 2>&1
    if not errorlevel 1 (
        echo   - Restarting Integra WinNAC service...
        sc start "Integra WinNAC" >> "%LOG_FILE%" 2>&1
        call :LogMsg "Rollback: service restart attempted"
    )
)

echo.
echo ============================================================
echo   ROLLBACK COMPLETE
echo ============================================================
echo   The system has been returned as close as possible to its
echo   pre-installation state. Review iWinNAC_install.log for details.
echo ============================================================
call :LogMsg "Rollback completed"
goto :eof

:FailAndStop
echo.
echo ============================================================
echo [ERROR] !FAIL_TITLE!
echo ============================================================
echo.
echo Reason:
echo   !FAIL_REASON!
echo.
echo Action:
echo   !FAIL_ACTION!
echo.
echo Log file:
echo   %LOG_FILE%
echo.
if exist "%ERR_FILE%" (
    echo Last certificate error:
    type "%ERR_FILE%"
    echo.
)
echo ============================================================
echo [ERROR] !FAIL_TITLE! >> "%LOG_FILE%"
echo Reason: !FAIL_REASON! >> "%LOG_FILE%"
echo Action: !FAIL_ACTION! >> "%LOG_FILE%"

call :Rollback

if exist "%THUMB_FILE%" del /f /q "%THUMB_FILE%" >nul 2>&1
if exist "%META_FILE%" del /f /q "%META_FILE%" >nul 2>&1
pause
exit /b 1
