@echo off
chcp 65001 >nul
setlocal enableextensions
REM ============================================================
REM  Instalator usługi NoviSerwis
REM  Plik zapisz w UTF-8 BEZ BOM (inaczej cmd wywali pierwszą linię)
REM ============================================================

REM --- Ustawienia ---
set "SERVICE_NAME=NoviSerwis_x64"
set "DISPLAY_NAME=Novitus - Serwer NoviSerwis"
set "SERVICE_DESC=Serwer komunikacyjny NoviSerwis"
set "SERVICE_EXE=NoviSerwis_x64.exe"
set "TARGET_DIR=C:\NOVITUS.SERVICES\NoviSerwis"
REM źródło = folder instalatora, cel = TARGET_DIR
set "SRC_DIR=%~dp0"
REM BIN_PATH wskazuje na CEL (stamtąd działa usługa), nie na folder instalatora
set "BIN_PATH=%TARGET_DIR%\%SERVICE_EXE%"
REM Nazwy używane przez starsze wersje instalatora - do posprzątania
set LEGACY_NAMES="Novitus - Serwer NoviSerwis" "NoviSerwis" "NoviSerwis_x64"

REM --- Uprawnienia administratora ---
net session >nul 2>&1
if errorlevel 1 (
    echo.
    echo Błąd: skrypt wymaga uprawnień administratora.
    echo.
    pause
    exit /b 1
)

REM --- Czy plik wykonywalny istnieje w źródle ---
if not exist "%SRC_DIR%%SERVICE_EXE%" (
    echo Błąd: nie znaleziono pliku "%SRC_DIR%%SERVICE_EXE%"
    pause
    exit /b 1
)

REM ============================================================
REM  KROK WSTĘPNY 1: cicha deinstalacja bardzo starej wersji
REM  (stary format configu - niczego nie zachowujemy, tylko czyścimy)
REM ============================================================
set "OLD_UNINST=C:\NOVITUS.SERVICES\NoviSerwis\unins000.exe"
if exist "%OLD_UNINST%" (
    echo [wstep] Wykryto stara wersje - odinstalowywanie...
    "%OLD_UNINST%" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
    timeout /t 5 /nobreak >nul
    echo        Stara wersja odinstalowana.
)

REM ============================================================
REM  KROK WSTĘPNY 2: zatrzymanie i usunięcie WSZYSTKICH usług z "NoviSerwis" w nazwie
REM ============================================================
echo [wstep] Wyszukiwanie i usuwanie starych uslug zawierajacych "NoviSerwis"...
for /f "tokens=2 delims=:" %%S in ('sc query state^= all ^| findstr /i "SERVICE_NAME:" ^| findstr /i "NoviSerwis"') do (
    call :RemoveOne "%%S"
)
echo        Zakonczono czyszczenie starych uslug.


REM ============================================================
REM  Zatrzymanie usługi przed kopiowaniem (zwalnia plik .exe)
REM ============================================================
echo [wstep] Zatrzymywanie uslugi przed kopiowaniem plikow...
call :RemoveOne "%SERVICE_NAME%"
sc query NoviSerwis_x64
REM daj systemowi chwile na zwolnienie uchwytu do pliku exe
timeout /t 2 /nobreak >nul


REM ============================================================
REM  KROK WSTĘPNY 3: skopiowanie całej zawartości folderu instalatora do celu
REM  (appsettings.json NIE istnieje w źródle - tworzy się dopiero przy wyborze ERP)
REM ============================================================
echo [wstep] Przygotowanie folderu docelowego: %TARGET_DIR%
if not exist "%TARGET_DIR%" mkdir "%TARGET_DIR%"
echo        Kopiowanie wszystkich plikow do %TARGET_DIR%...
xcopy "%SRC_DIR%." "%TARGET_DIR%\" /E /I /Y >nul
if errorlevel 1 (
    echo Blad kopiowania plikow.
    pause
    exit /b 1
)
echo        Pliki skopiowane.
echo.

REM ============================================================
REM  KROK WSTĘPNY 4: wybór ERP (pomijany, jeśli program już skonfigurowany)
REM ============================================================
if exist "%TARGET_DIR%\appsettings.json" (
    echo [wstep] Znaleziono appsettings.json - program juz skonfigurowany.
    echo        Wybor ERP pominiety, zachowuje istniejaca konfiguracje.
) else (
    echo.
    echo === Wybor systemu ERP ===
    echo   1 - Nexo
    echo   2 - Optima
    echo.
    call :ChooseErp
    if errorlevel 1 goto :fail
)
echo.

REM ============================================================
REM  GŁÓWNA INSTALACJA USŁUGI
REM ============================================================
echo === Instalacja usługi "%DISPLAY_NAME%" ===
echo Plik: %BIN_PATH%
echo.
echo [1/4] Usuwanie poprzednich instalacji...
call :RemoveOne "%SERVICE_NAME%"
if errorlevel 1 goto :fail
for %%N in (%LEGACY_NAMES%) do (
    call :RemoveOne %%N
    if errorlevel 1 goto :fail
)
call :RemoveByDisplayName
if errorlevel 1 goto :fail
call :InstallService || goto :fail
call :StartService   || goto :fail
echo.
echo Instalacja zakończona pomyślnie.
sc query "%SERVICE_NAME%" | findstr /i "SERVICE_NAME STATE"
echo.
pause
exit /b 0

:fail
echo.
echo === Instalacja NIE powiodła się ===
echo.
pause
exit /b 1

REM ============================================================
REM ============================================================
REM   PROCEDURY - kod główny NIGDY tu nie wchodzi liniowo
REM   (powyżej jest exit /b, więc jest bariera)
REM ============================================================
REM ============================================================

REM ============================================================
REM  :ChooseErp - wybór systemu ERP i utworzenie appsettings.json
:ChooseErp
set "ERP_CHOICE="
set /p "ERP_CHOICE=Wybierz system [1=Nexo, 2=Optima]: "
if "%ERP_CHOICE%"=="1" (
    set "ERP_SUFFIX=nexo"
) else if "%ERP_CHOICE%"=="2" (
    set "ERP_SUFFIX=optima"
) else (
    echo        Nieprawidlowy wybor. Wpisz 1 lub 2.
    goto :ChooseErp
)
if not exist "%TARGET_DIR%\appsettings_%ERP_SUFFIX%.txt" (
    echo Blad: brak pliku "%TARGET_DIR%\appsettings_%ERP_SUFFIX%.txt"
    exit /b 1
)
copy /Y "%TARGET_DIR%\appsettings_%ERP_SUFFIX%.txt" "%TARGET_DIR%\appsettings.json" >nul
if errorlevel 1 (
    echo Blad kopiowania konfiguracji.
    exit /b 1
)
echo        Skonfigurowano: %ERP_SUFFIX% -^> appsettings.json
exit /b 0

REM ============================================================
REM  :RemoveOne <nazwa_usługi>   - zatrzymuje i usuwa, jeśli istnieje
:RemoveOne
set "_svc=%~1"
if "%_svc%"=="" exit /b 0
sc query "%_svc%" >nul 2>&1
if errorlevel 1 exit /b 0
echo       Znaleziono usługę "%_svc%" - zatrzymywanie i usuwanie...
sc stop "%_svc%" >nul 2>&1
call :WaitForState "%_svc%" STOPPED 30 >nul
sc delete "%_svc%" >nul 2>&1
REM Po sc delete usługa może zostać "marked for deletion" dopóki ktoś
REM trzyma otwarty uchwyt (np. otwarte services.msc) - czekamy.
set /a _i=0
:rm_wait
sc query "%_svc%" >nul 2>&1
if errorlevel 1 (
    echo       Usunięto: "%_svc%"
    exit /b 0
)
set /a _i+=1
if %_i% geq 20 (
    echo.
    echo       Nie udało się usunąć usługi "%_svc%".
    echo       Prawdopodobnie stan "marked for deletion" - zamknij services.msc
    echo       i Podgląd zdarzeń, potem uruchom skrypt ponownie.
    echo       Jeśli to nie pomoże, konieczny restart komputera.
    exit /b 1
)
timeout /t 1 /nobreak >nul
goto :rm_wait

REM ============================================================
REM  Usuwa usługę kolidującą nazwą WYŚWIETLANĄ (przyczyna błędu 1078)
:RemoveByDisplayName
set "_key="
for /f "tokens=1,* delims==" %%a in ('sc GetKeyName "%DISPLAY_NAME%" 2^>nul ^| findstr "="') do set "_key=%%b"
if not defined _key exit /b 0
:trim_key
if "%_key:~0,1%"==" " (
    set "_key=%_key:~1%"
    goto :trim_key
)
if "%_key%"=="" exit /b 0
echo       Nazwa wyświetlana zajęta przez usługę "%_key%".
call :RemoveOne "%_key%"
exit /b %errorlevel%

REM ============================================================
:InstallService
echo [2/4] Tworzenie usługi...
REM UWAGA: spacja PO znaku "=", brak spacji PRZED.
REM Ścieżka w podwójnych, escape'owanych cudzysłowach - obsługa spacji w katalogu.
sc create "%SERVICE_NAME%" binPath= "\"%BIN_PATH%\"" DisplayName= "%DISPLAY_NAME%" start= auto obj= LocalSystem
if errorlevel 1 (
    echo       Błąd tworzenia usługi. Kod: %errorlevel%
    echo       1078 = nazwa lub nazwa wyświetlana nadal zajęta ^(sprawdź services.msc^)
    exit /b 1
)
echo [3/4] Konfiguracja...
sc description "%SERVICE_NAME%" "%SERVICE_DESC%" >nul 2>&1
REM Automatyczny restart po awarii: po 5 s, po 10 s, potem co 60 s; licznik zeruj po 24 h
sc failure "%SERVICE_NAME%" reset= 86400 actions= restart/5000/restart/10000/restart/60000 >nul 2>&1
exit /b 0

REM ============================================================
:StartService
echo [4/4] Uruchamianie usługi...
sc start "%SERVICE_NAME%" >nul 2>&1
if errorlevel 1 (
    echo       Polecenie start zwróciło błąd %errorlevel%.
    goto :startFailed
)
REM sc start jest asynchroniczne - trzeba odpytać stan
call :WaitForState "%SERVICE_NAME%" RUNNING 45
if errorlevel 1 goto :startFailed
echo       Usługa działa.
exit /b 0
:startFailed
echo.
echo       --- Diagnostyka ---
sc query "%SERVICE_NAME%"
sc queryex "%SERVICE_NAME%" | findstr /i "WIN32_EXIT_CODE SERVICE_EXIT_CODE"
echo.
echo       Najczęstsze przyczyny:
echo        1053 - program nie jest usługą Windows (nie wywołuje
echo               StartServiceCtrlDispatcher).
echo        1067 - proces zakończył się sam (błąd konfiguracji, brak portu, brak pliku).
echo        1069 - błąd logowania: nieprawidłowe konto lub hasło.
echo        5    - brak uprawnień konta do zasobu (np. baza SQL, pliki).
echo       Sprawdź też: Podgląd zdarzeń -^> Dzienniki systemu Windows -^> Aplikacja/System.
echo       oraz logi aplikacji w: %TARGET_DIR%\Logs
exit /b 1

REM ============================================================
REM  :WaitForState <nazwa> <STAN> <maks_sekund>
:WaitForState
set "_wsvc=%~1"
set "_want=%~2"
set /a _max=%~3
set /a _n=0
:ws_loop
sc query "%_wsvc%" 2>nul | find "STATE" | find "%_want%" >nul
if not errorlevel 1 exit /b 0
set /a _n+=1
if %_n% geq %_max% exit /b 1
timeout /t 1 /nobreak >nul
goto :ws_loop