@echo off
setlocal enabledelayedexpansion
cls

REM ============================================================
REM  2_Primeira_Instalacao_Albert.bat  v4.0  (com bootstrap inline)
REM ============================================================
REM
REM  Configura um Albert para um veiculo especifico.
REM
REM  Detecta automaticamente o estado do device:
REM
REM  [Caminho A — Albert ja roda]
REM    whoami responde → mostra identidade → install_from_sd
REM    popula NVS via /contr.txt no SD → reset → monitor.
REM
REM  [Caminho B — ESP32 sem firmware Albert (bootstrap inline)]
REM    whoami nao responde → pede numSerie manual + versao alvo →
REM    POST /ota_target/device/<NS> → push --bootstrap (grava
REM    firmware em app0 via esptool encrypted_write, K3 cifra) →
REM    espera boot → desregistra target → whoami valida → segue
REM    pro install_from_sd → reset → monitor.
REM
REM  Pre-condicoes (ver 0_Pre_Requisitos.md):
REM    - ESP32 ja passou pela Tacita (K3 burnado, encryption ATIVA,
REM      bootloader+PT+otadata cifrados).
REM    - SD inserido no Albert com /contr.txt v1.8.x configurado
REM      pra o veiculo alvo (sigla, placa, hab, DL, EDGEV1).
REM    - Cabo USB conectado, COM livre.
REM    - Python + pyserial + esptool + cryptography no PATH.
REM    - Endpoint /service/api/plaintext_firmware no AlbertService.
REM    - Versao alvo (.bin.k1enc) ja disponivel no servidor.
REM ============================================================

set "IOT_HOST=http://iot.mgconnect.online"
set "TITLE=Albert Flash V3 - Primeira Instalacao (com bootstrap inline)"
set "SERIAL_TOOL=%~dp0tools\albert_serial.py"
set "PUSH_TOOL=%~dp0tools\usb_esptool_push.py"
set "BIN_DIR=%~dp0bin"

echo ============================================================
echo  %TITLE%
echo ============================================================
echo.

REM Pre-flight
where python >nul 2>&1
if errorlevel 1 (
    echo [ERRO] Python nao encontrado no PATH.
    pause
    exit /b 1
)
where curl >nul 2>&1
if errorlevel 1 (
    echo [ERRO] curl nao encontrado no PATH.
    pause
    exit /b 1
)
if not exist "%SERIAL_TOOL%" (
    echo [ERRO] tools\albert_serial.py nao encontrado.
    pause
    exit /b 1
)
if not exist "%PUSH_TOOL%" (
    echo [ERRO] tools\usb_esptool_push.py nao encontrado.
    pause
    exit /b 1
)
if not exist "%BIN_DIR%" mkdir "%BIN_DIR%" 2>nul

REM ============================================================
REM ETAPA 1: Porta COM
REM ============================================================
echo [1] Detectando porta COM do ESP32...
for /f %%P in ('python "%SERIAL_TOOL%" detect-port 2^>nul') do set "COM_PORT=%%P"
if not defined COM_PORT (
    echo [ERRO] Nenhuma porta serial valida detectada.
    pause
    exit /b 1
)
echo  Porta detectada: !COM_PORT!
echo.

REM ============================================================
REM ETAPA 2: Tenta whoami pra detectar estado
REM ============================================================
echo [2] Lendo identidade atual do device via whoami...
echo  ^(envia comando "whoami" via serial — pode levar 5-10s^)
echo.
set "NS_ATUAL="
set "MOD_ATUAL="
set "SIGLA_ATUAL="
set "PLACA_ATUAL="
set "SW_ATUAL="
set "RUN_ATUAL="
for /f "tokens=1,2 delims==" %%K in ('python "%SERIAL_TOOL%" whoami !COM_PORT! 2^>nul') do (
    if "%%K"=="numSerie" set "NS_ATUAL=%%L"
    if "%%K"=="mod"      set "MOD_ATUAL=%%L"
    if "%%K"=="sigla"    set "SIGLA_ATUAL=%%L"
    if "%%K"=="placa"    set "PLACA_ATUAL=%%L"
    if "%%K"=="sw"       set "SW_ATUAL=%%L"
    if "%%K"=="running"  set "RUN_ATUAL=%%L"
)

if defined NS_ATUAL goto ALBERT_RUNNING

REM ============================================================
REM BOOTSTRAP INLINE — Albert nao responde, flashar primeiro
REM ============================================================
echo  whoami nao respondeu — ESP32 sem firmware Albert detectado.
echo  Entrando em modo BOOTSTRAP inline.
echo.
echo ============================================================
echo  BOOTSTRAP — flashar Albert antes de popular NVS
echo ============================================================
echo  Como o firmware Albert ainda nao esta no device, voce precisa
echo  fornecer manualmente:
echo    - numSerie ^(do label/QR fisico do ESP32, deve bater com BLK2 eFuse^)
echo    - versao alvo ^(ex: v2.0.0.bin^), com .bin.k1enc disponivel no servidor
echo.
set NS_ATUAL=
set /p NS_ATUAL=  numSerie do device:
if not defined NS_ATUAL (
    echo [ERRO] numSerie vazio. Abortando.
    pause
    exit /b 1
)
set TARGET_INPUT=
set /p TARGET_INPUT=  Versao alvo do firmware Albert ^(ex: v2.0.0.bin^):
if not defined TARGET_INPUT (
    echo [ERRO] Versao vazia. Abortando.
    pause
    exit /b 1
)

echo.
echo  Vou:
echo    1. Registrar target !TARGET_INPUT! pra !NS_ATUAL! no servidor.
echo    2. Baixar firmware plaintext via HTTPS ^(RAM, nunca disco^).
echo    3. esptool stub --encrypt em app0 ^(0x10000^). K3 cifra ao gravar.
echo    4. hard_reset → Albert deve bootar com Sicherung 0 ^(NVS vazia^).
echo    5. install_from_sd via serial pra popular NVS do /contr.txt.
echo.
set CONFIRMA=
set /p CONFIRMA=  Confirma bootstrap + instalacao de !NS_ATUAL! com !TARGET_INPUT!? [SIM/nao]:
if /i not "!CONFIRMA!"=="SIM" (
    echo Cancelado pelo operador.
    pause
    exit /b 0
)
echo.

echo  POST /ota_target/device/!NS_ATUAL!  payload={"versao":"!TARGET_INPUT!"}
curl -fsS -X POST -H "Content-Type: application/json" ^
    -d "{\"versao\":\"!TARGET_INPUT!\"}" ^
    "!IOT_HOST!/service/api/ota_target/device/!NS_ATUAL!" ^
    -o "!BIN_DIR!\ota_target_resp.json" 2>nul
if errorlevel 1 (
    echo [ERRO] Falha ao registrar target. Verifique:
    echo  - Conexao com !IOT_HOST!
    echo  - Versao !TARGET_INPUT! ^(arquivo .bin.k1enc^) existe no servidor
    echo  - numSerie !NS_ATUAL! existe na base do servidor
    pause
    exit /b 1
)
echo  Target registrado.
echo.

echo  Empurrando firmware via esptool ^(modo bootstrap, app0^)...
echo.
python "%PUSH_TOOL%" --port !COM_PORT! --numserie !NS_ATUAL! --base-url "!IOT_HOST!" --bootstrap --offset 0x10000
set "PUSH_RC=!errorlevel!"
echo.
if not "!PUSH_RC!"=="0" (
    echo [ERRO] bootstrap push falhou ^(rc=!PUSH_RC!^).
    pause
    exit /b 1
)

echo  Desregistrando target ^(fecha ciclo CMD12^)...
curl -fsS -X POST -H "Content-Type: application/json" ^
    -d "{\"versao\":\"\"}" ^
    "!IOT_HOST!/service/api/ota_target/device/!NS_ATUAL!" ^
    -o "!BIN_DIR!\ota_target_resp.json" 2>nul
if errorlevel 1 (
    echo  [AVISO] Falha ao desregistrar target. Continua mesmo assim.
)
echo.

echo  Aguardando boot do Albert ^(~10s^)...
timeout /t 10 /nobreak >nul

echo  Validando via whoami...
for /f "tokens=1,2 delims==" %%K in ('python "%SERIAL_TOOL%" whoami !COM_PORT! 2^>nul') do (
    if "%%K"=="numSerie" set "NS_ATUAL=%%L"
    if "%%K"=="mod"      set "MOD_ATUAL=%%L"
    if "%%K"=="sigla"    set "SIGLA_ATUAL=%%L"
    if "%%K"=="placa"    set "PLACA_ATUAL=%%L"
    if "%%K"=="sw"       set "SW_ATUAL=%%L"
    if "%%K"=="running"  set "RUN_ATUAL=%%L"
)
if not defined NS_ATUAL (
    echo [ERRO] Albert nao respondeu whoami apos bootstrap.
    echo  Possibilidades:
    echo   - Bootstrap nao gravou direito ^(ver logs do esptool acima^).
    echo   - Albert bootou mas demora mais que 10s pra inicializar serial.
    echo     Pode tentar abrir monitor manualmente ^(4_Monitor_Serial_Albert.bat^).
    echo   - eFuse BLK1 K3 errada ^(decifragem da flash falha^).
    pause
    exit /b 1
)
echo  Albert bootou — numSerie reportado: !NS_ATUAL!  SW: !SW_ATUAL!
echo  ^(numSerie do whoami pode estar vazio se NVS ainda nao populada — install_from_sd vai resolver.^)
echo.

REM Fluxo continua direto na ETAPA 3 (confirmacao + install_from_sd)

:ALBERT_RUNNING
REM ============================================================
REM ETAPA 3: Mostrar identidade + confirmacao
REM ============================================================
echo [3] Identidade do device:
echo    numSerie : !NS_ATUAL!
echo    sigla    : !SIGLA_ATUAL!
echo    placa    : !PLACA_ATUAL!
echo    modelo   : !MOD_ATUAL!
echo    firmware : !SW_ATUAL!
if defined RUN_ATUAL echo    particao : !RUN_ATUAL!
echo.
echo ============================================================
echo  IMPORTANTE:
echo   - Confirme que o SD inserido no Albert tem /contr.txt v1.8.x
echo     correto pro veiculo alvo.
echo   - Apos esta instalacao, NVS sera sobrescrita: sigla, placa,
echo     hab, DL, EDGEV1 serao os valores do contr.txt no SD.
echo   - numSerie no contr.txt precisa ser '!NS_ATUAL!' ^(= device atual^)
echo     ou tacitaCheck vai falhar no proximo boot.
echo ============================================================
echo.
set CONFIRMA=
set /p CONFIRMA=  Confirma popular NVS deste device? [SIM/nao]:
if /i not "!CONFIRMA!"=="SIM" (
    echo Cancelado pelo operador.
    pause
    exit /b 0
)
echo.

REM ============================================================
REM ETAPA 4: install_from_sd
REM ============================================================
echo [4] Enviando install_from_sd via serial...
echo  ^(le /contr.txt do SD, popula NVS via Preferences API,
echo   hardware K3 cifra cada write na flash^)
echo.
python "%SERIAL_TOOL%" install-from-sd !COM_PORT!
set "INSTALL_RC=!errorlevel!"
echo.
if not "!INSTALL_RC!"=="0" (
    echo [ERRO] install_from_sd falhou ^(rc=!INSTALL_RC!^).
    echo Veja as linhas anteriores pra causa ^(no_contr_txt, nvs_empty etc^).
    pause
    exit /b 1
)
echo  OK — NVS atualizada conforme /contr.txt.
echo.

REM ============================================================
REM ETAPA 5: Hard reset
REM ============================================================
echo [5] Resetando device para revalidar tacitaCheck e edgeActive...
python "%SERIAL_TOOL%" reset !COM_PORT!
echo  Reset enviado. Aguardando boot ^(~5s^)...
timeout /t 5 /nobreak >nul
echo.

REM ============================================================
REM ETAPA 6: Monitor serial pra validacao
REM ============================================================
echo [6] Abrindo monitor serial pra validacao
echo ============================================================
echo  Procure no log do boot:
echo    Albert N - num serie !NS_ATUAL!
echo    Sicherung 1
echo    EDGEV1 aplicado em edgeActive.
echo.
echo  Se aparecer Sicherung 0 ou outro numSerie, algo deu errado.
echo  Para sair do monitor: CTRL + ]
echo ============================================================
echo.

python -m serial.tools.miniterm !COM_PORT! 115200

echo.
echo ============================================================
echo  Primeira Instalacao concluida.
echo  Device !NS_ATUAL! pronto pra ir pro veiculo.
echo ============================================================
pause
