@echo off

:: -----------------------------------------------
:: WOW64 re-spawn - SOMENTE se WOW64 verdadeiro (PROCESSOR_ARCHITEW6432 setado).
:: Pra Win 32-bit nativo, NAO faz respawn - em vez disso usa Corretto 8 x86
:: (decidido em :detect_arch).
::
:: Caso WOW64: tenta sysnative direto e PowerShell .NET como fallback.
:: -----------------------------------------------
if "%_A3_RESPAWNED%"=="1" goto :_after_respawn
if not defined PROCESSOR_ARCHITEW6432 goto :_after_respawn

echo [Respawn] WOW64 detectado (PA=%PROCESSOR_ARCHITECTURE% AW6432=%PROCESSOR_ARCHITEW6432%) - re-lancando cmd 64-bit
set "_A3_RESPAWNED=1"

:: METODO 1: sysnative direto
"%windir%\sysnative\cmd.exe" /c ""%~f0" %*"
set "_RC=%errorlevel%"
if "%_RC%"=="0" exit /b 0
echo [Respawn] M1: errorlevel=%_RC% - tentando M2 (PowerShell .NET)

:: METODO 2: PowerShell .NET StartProcess (opera fora do WOW64 fs redirect)
powershell -NoProfile -ExecutionPolicy Bypass -Command "try { $cmd = (Join-Path $env:windir 'sysnative\cmd.exe'); if (-not (Test-Path $cmd)) { exit 99 }; $p = Start-Process -FilePath $cmd -ArgumentList @('/c', ('\"' + '%~f0' + '\" ' + '%*')) -Wait -NoNewWindow -PassThru; exit $p.ExitCode } catch { exit 99 }"
set "_RC=%errorlevel%"
if "%_RC%"=="0" exit /b 0
if not "%_RC%"=="99" exit /b %_RC%

echo [Respawn] M2 tambem falhou - continuando no contexto atual (pode dar erro 216)
set "_A3_RESPAWNED="

:_after_respawn

:: -----------------------------------------------
:: PRE-DELAYED-EXPANSION sanitization. EXECUTA AQUI - ANTES de setlocal
:: EnableDelayedExpansion. Dois problemas distintos com username "BEM VINDO bang":
::
:: PROBLEMA 1 (delayed expansion): `bang` em path expandido em delayed
:: expansion mode eh interpretado como marcador de variavel e silenciosamente
:: removido. Quebra mkdir/extract dentro do bat.
::
:: PROBLEMA 2 (Java URL parser): Java usa `bang` como separador entre arquivo
:: JAR e caminho interno em jar: URLs [jar:file:///path.jar!/inner]. Quando
:: JARs do app estao sob path com `bang`, ServiceLoader/classpath quebra com
:: InvalidPathException. 8.3 conversion NAO resolve porque atalhos do Windows
:: resolvem 8.3 de volta pra long form na hora de executar.
::
:: Caso real (mai/2026): cliente Win10 username "BEM VINDO bang".
::   - v16 com 8.3 [BEMVIN~1] resolveu instalacao mas app falhou em runtime
::     com "java.util.ServiceConfigurationError: javax.websocket.ContainerProvider"
::     porque atalho do Desktop resolveu pra long form com bang.
::
:: SOLUCAO v17: detectar `bang` no path ORIGINAL [pre-8.3]. Se presente,
:: instalar em %PUBLIC% [sem bang]. Caso contrario, 8.3 conversion normal
:: [cobre acentos, trailing space, etc].
:: -----------------------------------------------
set "_FORCE_PUBLIC=0"
echo "%USERPROFILE%" | findstr /L "!" >nul 2>&1
if not errorlevel 1 set "_FORCE_PUBLIC=1"
echo "%LOCALAPPDATA%" | findstr /L "!" >nul 2>&1
if not errorlevel 1 set "_FORCE_PUBLIC=1"

if "%_FORCE_PUBLIC%"=="1" goto :_pre_force_public

:: Caminho normal: 8.3 conversion [acentos, trailing space, espacos]
for %%I in ("%LOCALAPPDATA%") do if exist "%%~fI\" set "LOCALAPPDATA=%%~sI"
for %%I in ("%USERPROFILE%") do if exist "%%~fI\" set "USERPROFILE=%%~sI"
for %%I in ("%APPDATA%") do if exist "%%~fI\" set "APPDATA=%%~sI"
for %%I in ("%TEMP%") do if exist "%%~fI\" set "TEMP=%%~sI"
for %%I in ("%TMP%") do if exist "%%~fI\" set "TMP=%%~sI"
goto :_pre_done

:_pre_force_public
echo [PRE] Username contem caractere especial incompativel com Java URL parser.
echo [PRE] Instalando em PUBLIC para evitar quebra de classpath JAR.
echo [PRE] Path original USERPROFILE: %USERPROFILE%
:: Cleanup defensivo: se v15-v16 ja tinha instalado sob o perfil corrompido,
:: renomeia [nao deleta] pra preservar dados em caso de problema. Rename
:: silencioso - se falhar [arquivos em uso, etc] o install novo em PUBLIC
:: funciona de qualquer forma.
if exist "%LOCALAPPDATA%\assinadora3\" ren "%LOCALAPPDATA%\assinadora3" "assinadora3.pre_v17" 2>nul
set "USERPROFILE=%PUBLIC%"
set "LOCALAPPDATA=%PUBLIC%\AppData\Local"
set "APPDATA=%PUBLIC%\AppData\Roaming"
mkdir "%PUBLIC%\AppData\Local" 2>nul
mkdir "%PUBLIC%\AppData\Roaming" 2>nul

:_pre_done

setlocal EnableExtensions EnableDelayedExpansion
title AssinadorA3 - Instalacao

:: -----------------------------------------------
:: Codepage: usa 850 (PT-BR DOS) em todas as versoes do Windows.
:: NAO usar 65001 (UTF-8): em Win7 sem KB2790113 ele quebra parsing
:: silenciosamente (for /f, where, etc. travam) abortando o bat.
:: O proprio bat nao contem caracteres nao-ASCII, entao 850 e suficiente.
:: Salva original para restaurar ao final.
:: -----------------------------------------------
set "_CP_ORIG="
for /f "tokens=2 delims=:" %%C in ('chcp 2^>nul') do set "_CP_ORIG=%%C"
if defined _CP_ORIG set "_CP_ORIG=!_CP_ORIG: =!"
chcp 850 >nul 2>&1

:: -----------------------------------------------
:: Log
:: -----------------------------------------------
set "LOGFILE=%TEMP%\assinadora3_install.log"
break > "%LOGFILE%" 2>nul

:: -----------------------------------------------
:: Variaveis
:: -----------------------------------------------
if not defined LOCALAPPDATA set "LOCALAPPDATA=%APPDATA%"

:: 8.3 conversion JA FOI feita PRE-delayed-expansion no topo do script
:: [necessario pra resolver caractere bang em username]. Aqui rodamos
:: apenas o sanitize_envs como segunda camada defensiva: se LOCALAPPDATA
:: aponta pra path inexistente [trailing space, corrupcao de env],
:: reconstroi a partir de USERPROFILE. Caso real cliente BEM VINDO bang.
call :sanitize_envs

set "DEST=%LOCALAPPDATA%\assinadora3"
set "JAR=%DEST%\AssinadorA3Install.jar"
set "JARTEMP=%DEST%\AssinadorA3Install.jar.tmp"
set "ASSINADORJAR=%DEST%\app\assinadorA3.jar"
set "URL=https://assinadora3.s3.us-east-1.amazonaws.com/release/AssinadorA3Install.jar"
:: Mirror HTTP fallback pra Win 7 sem TLS 1.2 - mesmo host, sem TLS
set "URL_MIRROR=http://assinadora3.s3.amazonaws.com/release/AssinadorA3Install.jar"
set "PORTABLE_DIR=%DEST%\corretto21"
set "JAVACMD="
set "JMAJOR=0"
set "MSI_ARCH=x64"
set "JAVA_MAJOR=21"
set "APP_FRESH=0"

call :log "============================================"
call :log "       AssinadorA3 - Instalador"
call :log "       BAT VER: 2026-05-28-publicfallback-v17"
call :log "============================================"
call :log ""
call :log "Log: !LOGFILE!"
call :log ""

call :detect_arch
call :log "Arquitetura: !MSI_ARCH!"
:: --- Diagnostico de ambiente (ajuda triagem em maquinas com erro) ---
call :diag_env
call :log "USERPROFILE=%USERPROFILE%"
call :log "LOCALAPPDATA=%LOCALAPPDATA%"
call :log "DEST=%DEST%"
call :log ""

:: -----------------------------------------------
:: 1) Detecta Java ]= 11 (ou instala portatil)
:: -----------------------------------------------
call :log "[1/5] Verificando Java..."
call :log "[DBG] MSI_ARCH=!MSI_ARCH! JAVA_MAJOR=!JAVA_MAJOR! PORTABLE_DIR=!PORTABLE_DIR!"

call :log "[DBG] chamando detect_corretto21"
call :detect_corretto21
if defined JAVACMD (
    call :log "Java Corretto 21 do sistema: !JAVACMD!"
    goto :java_validado
)

call :log "[DBG] chamando detect_portable_java"
call :detect_portable_java
if defined JAVACMD (
    call :log "Java portatil de execucao anterior: !JAVACMD!"
    goto :java_validado
)

call :log "[DBG] chamando detect_modern_java"
call :detect_modern_java
if defined JAVACMD (
    call :log "Java !JMAJOR! valido no sistema: !JAVACMD!"
    goto :java_validado
)

call :log "Java >= 11 nao encontrado. Baixando Corretto 21 portatil..."
call :log ""
call :install_portable_corretto
if not defined JAVACMD (
    call :log ""
    call :log "[ERRO FATAL] Nao foi possivel obter Java 21."
    call :log "Verifique sua conexao com a internet."
    call :log "Log salvo em: !LOGFILE!"
    echo.
    pause
    exit /b 1
)

:java_validado
call :log "Java pronto: !JAVACMD!"
call :log ""

:: -----------------------------------------------
:: 2) Pasta
:: -----------------------------------------------
call :log "[2/5] Preparando pasta..."
if not exist "%DEST%\" (
    mkdir "%DEST%" 2>nul
    if errorlevel 1 (
        call :log "[AVISO] Pasta padrao indisponivel. Usando alternativa..."
        set "DEST=%USERPROFILE%\assinadora3"
        set "JAR=!DEST!\AssinadorA3Install.jar"
        set "JARTEMP=!DEST!\AssinadorA3Install.jar.tmp"
        set "ASSINADORJAR=!DEST!\app\assinadorA3.jar"
        mkdir "!DEST!" 2>nul
    )
)
call :log "Pasta: !DEST!"
call :log ""

if exist "!JARTEMP!" del /F /Q "!JARTEMP!" 2>nul
if exist "!DEST!\updater.lock" (
    call :log "Removendo lock anterior..."
    del /F /Q "!DEST!\updater.lock" 2>nul
)

:: -----------------------------------------------
:: 3) Baixa SEMPRE o jar instalador (~50KB).
:: Otimizacao de "pular download se fresh" foi removida porque criava
:: armadilha de "rodar 2x": apos bump de installer-version, a primeira
:: execucao usava o jar local antigo (codigo desatualizado) e so a
:: segunda usava o jar novo. Mais simples e robusto: sempre baixar.
:: -----------------------------------------------
call :log "[3/5] Baixando instalador..."
:: Cache-buster: append ?cb=RANDOM[TIME] na URL pra invalidar cache do
:: WinINet/IE no Win 7. MSXML2.XMLHTTP usa WinINet e ignora Cache-Control
:: "no-cache" do S3 - servia versao antiga mesmo apos novo upload.
:: S3 ignora query strings (retorna mesmo objeto), entao isso e seguro.
:: Caso real (mai/2026): usuario VENDAS02 baixava JAR antigo mesmo apos
:: upload do novo, ate adicionarmos o cache-buster.
set "_CB=%RANDOM%%TIME:~6,2%%TIME:~9,2%"
set "_CB=!_CB: =0!"
call :download "!URL!?cb=!_CB!" "!JARTEMP!"

:: Fallback HTTP mirror (Win 7 sem TLS 1.2):
:: Mesma logica do Corretto - se HTTPS falhou em todos 5 metodos por TLS
:: ausente, tenta http://assinadora3.s3.amazonaws.com (HTTP puro funciona via
:: bitsadmin/certutil mesmo sem TLS 1.2).
if not exist "!JARTEMP!" (
    call :log "  [FALLBACK] Tentando mirror HTTP do instalador (sem TLS)..."
    call :download "!URL_MIRROR!?cb=!_CB!" "!JARTEMP!"
)

if not exist "!JARTEMP!" (
    call :log ""
    call :log "[ERRO] Nao foi possivel baixar o instalador (HTTPS e HTTP)."
    call :log "Verifique sua conexao com a internet."
    echo.
    pause
    exit /b 1
)
for %%A in ("!JARTEMP!") do if %%~zA lss 10000 (
    call :log "[ERRO] Arquivo baixado muito pequeno: %%~zA bytes"
    del /F /Q "!JARTEMP!" 2>nul
    echo.
    pause
    exit /b 1
)
:: Substitui o jar antigo pelo recem-baixado. PROBLEMA: handle pode estar
:: preso por javaw orfao, AV scanner [Defender abre o jar pra scan recem
:: baixado] ou indexador. Move /Y falha SILENCIOSAMENTE com [2 redir nul]
:: e na proxima execucao o instalador roda o jar VELHO num ciclo infinito.
:: Estrategia escalonada:
::   1. move direto
::   2. kill java orfaos + retry
::   3. rename do destino [FILE_RENAME aceita handle aberto em muitos casos]
::   4. aguarda AV soltar lock + delete forcado
::   5. abort com tasklist no log
:: NAO matamos powershell.exe - pode estar sendo usado por outros apps do
:: usuario [matar e disruptivo demais].
move /Y "!JARTEMP!" "!JAR!" >nul 2>&1
if not exist "!JARTEMP!" goto :jar_move_ok

call :log "[AVISO] Move inicial falhou. Matando processos Java/script orfaos..."
taskkill /F /IM javaw.exe >nul 2>&1
taskkill /F /IM java.exe >nul 2>&1
taskkill /F /IM cscript.exe >nul 2>&1
taskkill /F /IM wscript.exe >nul 2>&1
ping -n 4 127.0.0.1 >nul 2>&1
move /Y "!JARTEMP!" "!JAR!" >nul 2>&1
if not exist "!JARTEMP!" goto :jar_move_ok

call :log "[AVISO] Tentando rename do jar antigo [contorna handle aberto]..."
attrib -R -H -S "!JAR!" >nul 2>&1
ren "!JAR!" "AssinadorA3Install.jar.%RANDOM%.old" >nul 2>&1
move /Y "!JARTEMP!" "!JAR!" >nul 2>&1
if not exist "!JARTEMP!" goto :jar_move_ok

call :log "[AVISO] Aguardando 8s para AV/indexador soltar lock..."
ping -n 9 127.0.0.1 >nul 2>&1
del /F /Q "!JAR!" >nul 2>&1
move /Y "!JARTEMP!" "!JAR!" >nul 2>&1
if not exist "!JARTEMP!" goto :jar_move_ok

call :log "[AVISO] Tentando copy /Y [usa write em vez de rename]..."
copy /Y "!JARTEMP!" "!JAR!" >nul 2>&1
if errorlevel 1 goto :jar_use_tmp
del /F /Q "!JARTEMP!" >nul 2>&1
goto :jar_move_ok

:jar_use_tmp
:: Ultima cartada: roda jar direto do .tmp. Caso real (mai/2026): cliente Win10
:: com handle preso no jar [nao por Java - tasklist Java vazio. Provavel
:: Defender ou indexador]. Em vez de abortar, executa o jar baixado mesmo
:: que nao tenhamos conseguido substituir o oficial.
call :log ""
call :log "[AVISO] Substituicao do jar oficial falhou."
call :log "[AVISO] Capturando diagnostico amplo no log..."
:: findstr usa espaco como separador de termos [OR implicito, sem regex].
:: /L = literal, /I = case insensitive.
tasklist /NH 2>nul | findstr /L /I "java.exe javaw.exe cscript.exe wscript.exe MsMpEng SearchIndexer SmartScreen explorer.exe" >> "%LOGFILE%" 2>nul
call :log ""
call :log "[INFO] Executando via tmp [jar oficial sera atualizado proxima execucao]."
set "JAR=!JARTEMP!"

:jar_move_ok
call :log "Download concluido."
call :log ""

:executar_instalador
:: -----------------------------------------------
:: 5) Executa instalador
:: -----------------------------------------------
call :log "[4/5] Executando instalador..."
call :log ""
cd /d "!DEST!"
"!JAVACMD!" -jar "!JAR!"
set "JAR_ERR=!ERRORLEVEL!"
call :log ""
call :log "Instalador encerrou - codigo: !JAR_ERR!"

:verificar_app
:: -----------------------------------------------
:: 6) Verifica e lanca app
:: -----------------------------------------------
call :log "[5/5] Verificando instalacao..."
if not exist "!ASSINADORJAR!" goto :app_nao_encontrado
call :log "AssinadorA3 instalado em: !ASSINADORJAR!"
:: Resolve o binario de execucao da GUI (javaw.exe se disponivel) FORA de
:: qualquer bloco IF para evitar problemas de parser do cmd.exe com
:: substring substitution (!VAR:a=b!) aninhada em if (...) em algumas builds.
call :resolve_appjava
:: O AtualizadorMain (java -jar AssinadorA3Install.jar) ja faz launchApp
:: internamente quando termina OK (exit=0). Se relancarmos aqui, sobe uma
:: 2a instancia que bate no AppLock e exibe dialog "ja em execucao". Por
:: isso so relancamos como FALLBACK quando o updater retornou erro.
if not "!JAR_ERR!"=="0" (
    call :log "Iniciando AssinadorA3 como fallback (updater retornou !JAR_ERR!)..."
    start "" "!APPJAVA!" -jar "!ASSINADORJAR!"
    call :log "AssinadorA3 iniciado."
) else (
    call :log "AssinadorA3 ja iniciado pelo updater (exit=0)."
)
goto :pos_verificacao
:app_nao_encontrado
call :log "[AVISO] assinadorA3.jar nao encontrado: !ASSINADORJAR!"
call :log "A instalacao pode nao ter sido concluida."
:pos_verificacao

if exist "!DEST!" copy /Y "%LOGFILE%" "!DEST!\instalar.log" >nul 2>&1
call :log ""
call :log "Log salvo em: !DEST!\instalar.log"
call :log "Em caso de problema, envie tambem: %LOGFILE%"
echo.
pause
:: Restaura codepage original antes de sair (evita deixar console em UTF-8
:: caso outro script seja executado em sequencia no mesmo cmd host).
if defined _CP_ORIG chcp !_CP_ORIG! >nul 2>&1
endlocal
exit /b 0

:: ==============================================
:: SUB-ROTINAS
:: ==============================================

:log
:: Sem usar blocos (...). Strings com parens em %~1 (ex.: "(x86)" ou
:: "(incompativel)") quebravam o parser quando expandidas dentro de
:: [ echo %~1 ] - o parens de DENTRO eram interpretados como abertura
:: de novo bloco. Usa GOTO sequencial pra contornar.
if "%~1"=="" goto :_log_empty
echo %~1
if defined LOGFILE echo %~1>>"%LOGFILE%"
exit /b 0
:_log_empty
echo.
if defined LOGFILE echo.>>"%LOGFILE%"
exit /b 0

:sanitize_envs
:: Detecta LOCALAPPDATA/USERPROFILE apontando pra paths inexistentes
:: e tenta recuperar a partir de fontes alternativas. Marca flags pra
:: que :diag_env logue o fix [LOGFILE pode nao existir aqui ainda].
:: Usa GOTO sequencial pra evitar 'if defined X if not exist Y' que
:: quebra em alguns shims AV.
set "_SAN_LOCALAPP_FIXED="
set "_SAN_LOCALAPP_OLD="
set "_SAN_USERPROFILE_FIXED="
set "_SAN_USERPROFILE_OLD="
if not defined LOCALAPPDATA goto :_se_check_user
if exist "%LOCALAPPDATA%\" goto :_se_check_user
if not defined USERPROFILE goto :_se_check_user
if not exist "%USERPROFILE%\AppData\Local\" goto :_se_check_user
set "_SAN_LOCALAPP_OLD=%LOCALAPPDATA%"
set "LOCALAPPDATA=%USERPROFILE%\AppData\Local"
set "_SAN_LOCALAPP_FIXED=1"
:_se_check_user
if not defined USERPROFILE goto :_se_done
if exist "%USERPROFILE%\" goto :_se_done
if not defined PUBLIC goto :_se_done
if not exist "%PUBLIC%\" goto :_se_done
set "_SAN_USERPROFILE_OLD=%USERPROFILE%"
set "USERPROFILE=%PUBLIC%"
set "_SAN_USERPROFILE_FIXED=1"
:_se_done
exit /b 0

:diag_env
:: Coleta informacoes do ambiente para o log - critico para triagem remota.
call :log "OS: %OS%  PROCESSOR_ARCHITECTURE: %PROCESSOR_ARCHITECTURE%"
if defined PROCESSOR_ARCHITEW6432 call :log "PROCESSOR_ARCHITEW6432: %PROCESSOR_ARCHITEW6432%"
:: Versao do Windows
ver >> "%LOGFILE%" 2>nul
:: Build/release detalhado
for /f "tokens=4-7 delims=[]. " %%A in ('ver 2^>nul') do (
    call :log "Win build: %%A.%%B.%%C.%%D"
)
:: Codepage atual
for /f "tokens=2 delims=:" %%C in ('chcp 2^>nul') do call :log "Codepage:%%C"
:: PowerShell version
where powershell >nul 2>&1
if not errorlevel 1 (
    for /f "delims=" %%P in ('powershell -NoProfile -Command "$PSVersionTable.PSVersion.ToString()" 2^>nul') do call :log "PowerShell: %%P"
) else (
    call :log "PowerShell: NAO INSTALADO"
)
:: tar / curl / forfiles - testa cada um e loga separadamente
call :log_cmd_avail tar
call :log_cmd_avail curl
call :log_cmd_avail forfiles
call :log_cmd_avail bitsadmin
call :log_cmd_avail certutil
:: Admin?
net session >nul 2>&1
if errorlevel 1 (call :log "Privilegio: usuario comum") else (call :log "Privilegio: ADMIN")
if defined _SAN_LOCALAPP_FIXED call :log "[FIX] LOCALAPPDATA estava corrompido. Antigo: %_SAN_LOCALAPP_OLD%"
if defined _SAN_LOCALAPP_FIXED call :log "[FIX] Novo LOCALAPPDATA: %LOCALAPPDATA%"
if defined _SAN_USERPROFILE_FIXED call :log "[FIX] USERPROFILE estava corrompido. Antigo: %_SAN_USERPROFILE_OLD%"
if defined _SAN_USERPROFILE_FIXED call :log "[FIX] Novo USERPROFILE: %USERPROFILE%"
exit /b 0

:log_cmd_avail
where %~1 >nul 2>&1
if errorlevel 1 (call :log "%~1: ausente") else (call :log "%~1: disponivel")
exit /b 0

:compute_skip_download
:: Pula download se APP_FRESH=1 e o jar instalador ja existe localmente.
:: O jar instalador ainda eh executado (recria atalho).
:: Sub-rotina isolada porque "if A if B action" em algumas builds com
:: shims antivirus de IFEO falha silenciosamente.
set "_SKIP_DOWNLOAD=0"
if not "!APP_FRESH!"=="1" exit /b 0
if exist "!JAR!" set "_SKIP_DOWNLOAD=1"
exit /b 0

:resolve_appjava
:: Resolve APPJAVA preferindo javaw.exe (sem janela CMD) se disponivel.
:: Manipulacao de string isolada aqui FORA de blocos if (...) aninhados,
:: que sao a fonte mais comum de erros de parser do cmd.exe.
set "APPJAVA=!JAVACMD!"
set "_HAS_JAVA_EXE=0"
:: Detecta presenca de "java.exe" no caminho sem usar substring substitution
:: dentro de if (...). Faz a comparacao em variaveis simples.
set "_TMP1=!JAVACMD:java.exe=!"
if not "!_TMP1!"=="!JAVACMD!" set "_HAS_JAVA_EXE=1"
if "!_HAS_JAVA_EXE!"=="1" (
    set "_JAVAW=!JAVACMD:java.exe=javaw.exe!"
    if exist "!_JAVAW!" set "APPJAVA=!_JAVAW!"
)
set "_TMP1="
set "_JAVAW="
set "_HAS_JAVA_EXE="
exit /b 0

:detect_arch
:: Default: x64 (caso mais comum)
set "MSI_ARCH=x64"
set "JAVA_MAJOR=21"

:: ARM64 nativo ou WOW emulated x86 em ARM64
if /i "%PROCESSOR_ARCHITECTURE%"=="ARM64" set "MSI_ARCH=aarch64"
if defined PROCESSOR_ARCHITEW6432 if /i "%PROCESSOR_ARCHITEW6432%"=="ARM64" set "MSI_ARCH=aarch64"

:: Caso Win 32-bit nativo: PA=x86 SEM AW6432.
:: Usa GOTO sequencial pra evitar 'if (...) if (...)' aninhado que quebra
:: parser CMD em algumas builds. Caso real Amanda VENDAS02 mai/2026.
if /i not "%PROCESSOR_ARCHITECTURE%"=="x86" exit /b 0
if defined PROCESSOR_ARCHITEW6432 exit /b 0
set "MSI_ARCH=x86"
set "JAVA_MAJOR=8"
set "PORTABLE_DIR=%DEST%\corretto8"
call :log "[Arch] Detectado Windows 32-bit nativo - usando Corretto 8 x86"
exit /b 0

:detect_corretto21
:: Corretto 21 instalado no sistema (admin install). Apenas x64 (ProgramFiles)
:: - nunca usar %ProgramFiles(x86)% em blocos for/if porque os parens NO NOME
:: vazam pro parser CMD em Win10+ algumas builds (ver :detect_java_any).
:: Corretto distribuido pela Amazon e SEMPRE x64; nao existe build x86.
set "JAVACMD="
set "_PF=%ProgramFiles%"
if not defined _PF set "_PF=C:\Program Files"
if not exist "!_PF!\Amazon Corretto\" exit /b 0
for /D %%J in ("!_PF!\Amazon Corretto\jre21*" "!_PF!\Amazon Corretto\jdk21*") do (
    if exist "%%~J\bin\java.exe" ( set "JAVACMD=%%~J\bin\java.exe" & exit /b 0 )
)
exit /b 0

:detect_portable_java
:: Java portatil extraido em DEST/PORTABLE_DIR.
:: Cleanup de corretto21 incompativel e feito no install_portable_corretto.
set "JAVACMD="
if not exist "%PORTABLE_DIR%\" exit /b 0
for /D %%J in ("%PORTABLE_DIR%\jdk*" "%PORTABLE_DIR%\jre*") do (
    if exist "%%J\bin\java.exe" ( set "JAVACMD=%%J\bin\java.exe" & exit /b 0 )
)
exit /b 0

:detect_modern_java
:: Encontra Java ]= 11 no sistema (valida versao)
set "JAVACMD="
call :detect_java_any
if not defined JAVACMD exit /b 0
call :check_java_version
if !JMAJOR! geq 11 exit /b 0
:: Versao antiga - rejeita
set "JAVACMD="
exit /b 0

:detect_java_any
:: Detecta Java SEM scan de Program Files. Versoes anteriores tentavam
:: scanear "Eclipse Adoptium", "Amazon Corretto", etc em ProgramFiles e
:: ProgramFiles(x86) - o ProgramFiles(x86) tem parens NO NOME que vazam
:: pro parser CMD em algumas builds Win10/11, causando
:: "\Eclipse foi inesperado neste momento" e abortando o bat.
:: Estrategia atual: so tenta JAVA_HOME e where. Se falhar, cai pro
:: install_portable_corretto que e nosso fallback robusto e SEM admin.
set "JAVACMD="
if defined JAVA_HOME call :_try_java_home
if defined JAVACMD exit /b 0
where java.exe >nul 2>&1
if not errorlevel 1 ( set "JAVACMD=java" & exit /b 0 )
exit /b 0

:_try_java_home
:: Roda FORA de qualquer bloco IF/FOR - protegido contra parens em JAVA_HOME.
if exist "%JAVA_HOME%\bin\java.exe" set "JAVACMD=%JAVA_HOME%\bin\java.exe"
exit /b 0

:check_java_version
set "JMAJOR=0"
set "JVER="
set "_JCHK=!JAVACMD!"
if /i "!_JCHK!"=="javaw" set "_JCHK=java"
if not "!_JCHK:javaw.exe=!"=="!_JCHK!" (
    set "_JCHK_J=!_JCHK:javaw.exe=java.exe!"
    if exist "!_JCHK_J!" set "_JCHK=!_JCHK_J!"
)
"!_JCHK!" -version > "%TEMP%\_jver.txt" 2>&1
for /f "tokens=3" %%V in ('findstr /i "version" "%TEMP%\_jver.txt" 2^>nul') do set "JVER=%%~V"
del /F /Q "%TEMP%\_jver.txt" 2>nul
if not defined JVER set "JVER=0"
set "JVER=!JVER:"=!"
for /f "tokens=1,2 delims=." %%A in ("!JVER!") do (
    if "%%A"=="1" ( set "JMAJOR=%%B" ) else ( set "JMAJOR=%%A" )
)
if not defined JMAJOR set "JMAJOR=0"
if "!JMAJOR!"=="" set "JMAJOR=0"
set "_JCHK=" & set "_JCHK_J="
exit /b 0

:install_portable_corretto
:: Baixa e extrai Corretto portatil (SEM admin, SEM PATH).
:: Variante (Corretto 21 x64 padrao OU Corretto 8 x86 fallback pra Win 32-bit)
:: decidida em :detect_arch via JAVA_MAJOR + MSI_ARCH.
set "JAVACMD="
set "CORRETTO_ZIP=%TEMP%\corretto%JAVA_MAJOR%.zip"
set "CORRETTO_URL=https://corretto.aws/downloads/latest/amazon-corretto-%JAVA_MAJOR%-%MSI_ARCH%-windows-jdk.zip"
call :log "Corretto target: Java %JAVA_MAJOR% %MSI_ARCH%"
call :log "  URL: %CORRETTO_URL%"

if not exist "%DEST%\" mkdir "%DEST%" 2>nul
:: Aborta cedo se mkdir falhou silencioso. Caso real: LOCALAPPDATA corrompido
:: aponta pra path inexistente, mkdir falha e seguir adiante so gera erros
:: enganosos depois. sanitize_envs deve ter resolvido antes - se chegou aqui
:: com falha, e algo mais grave.
if exist "%DEST%\" goto :_ipc_dest_ok
call :log "[ERRO] Nao foi possivel criar pasta destino: %DEST%"
call :log "        Path pode ser invalido ou parent inexistente."
exit /b 0
:_ipc_dest_ok

:: Limpa Corretto incompativel se Win 32-bit. GOTO sequencial pra evitar
:: if aninhado.
if /i not "%MSI_ARCH%"=="x86" goto :_ipc_skip_clean
if not exist "%DEST%\corretto21\" goto :_ipc_skip_clean
call :log "Removendo Corretto 21 anterior (incompativel com Win 32-bit)..."
rmdir /S /Q "%DEST%\corretto21" 2>nul
:_ipc_skip_clean

call :log ""
call :log "============================================"
call :log "  Baixando Corretto 21 [aprox 200MB]"
call :log "  Pode levar de 1 a 10 minutos dependendo"
call :log "  da velocidade da sua conexao."
call :log "  Aguarde - barra de progresso a seguir..."
call :log "============================================"
call :log ""
call :download "!CORRETTO_URL!" "!CORRETTO_ZIP!"

:: Fallback HTTP MIRROR (Win 7 sem TLS 1.2):
:: Caso real (mai/2026): cliente Win 7 SP1 sem KB3140245 nao consegue TLS 1.2
:: e os 5 metodos de download falham todos (corretto.aws exige TLS 1.2 desde
:: 2023). Mantemos mirror HTTP em http://assinadora3.s3.amazonaws.com com
:: acesso publico sem TLS. S3 path-style HTTP ainda eh suportado pra buckets
:: legacy. bitsadmin/certutil funcionam pra HTTP sem precisar TLS algum.
if not exist "!CORRETTO_ZIP!" (
    call :log "  [FALLBACK] Tentando mirror HTTP (sem TLS) - Win 7 sem KB3140245..."
    set "MIRROR_URL=http://assinadora3.s3.amazonaws.com/release/corretto%JAVA_MAJOR%-%MSI_ARCH%.zip"
    call :log "  Mirror URL: !MIRROR_URL!"
    call :download "!MIRROR_URL!" "!CORRETTO_ZIP!"
)

if not exist "!CORRETTO_ZIP!" (
    call :log "[ERRO] Falha ao baixar Corretto %JAVA_MAJOR% %MSI_ARCH% (HTTPS e HTTP)."
    exit /b 0
)
for %%A in ("!CORRETTO_ZIP!") do if %%~zA lss 1000000 (
    call :log "[ERRO] Download Corretto muito pequeno: %%~zA bytes"
    del /F /Q "!CORRETTO_ZIP!" 2>nul
    exit /b 0
)

call :log "Extraindo Corretto %JAVA_MAJOR% portatil..."
if exist "%PORTABLE_DIR%\" rmdir /S /Q "%PORTABLE_DIR%" 2>nul
mkdir "%PORTABLE_DIR%" 2>nul
:: Verifica criacao antes de prosseguir; sem isso, pushd/tar/PowerShell todos
:: falham com mensagens enganosas tipo "caminho nao encontrado".
if exist "%PORTABLE_DIR%\" goto :_ipc_portable_ok
call :log "[ERRO] Nao foi possivel criar pasta portatil: %PORTABLE_DIR%"
exit /b 0
:_ipc_portable_ok

:: Metodo 1: tar (Windows 10 1803+) - mais rapido e confiavel
where tar >nul 2>&1
if not errorlevel 1 (
    pushd "%PORTABLE_DIR%"
    tar -xf "!CORRETTO_ZIP!"
    popd
)

:: Verifica se extraiu
set "_EXTRACTED=0"
for /D %%J in ("%PORTABLE_DIR%\jdk*" "%PORTABLE_DIR%\jre*") do (
    if exist "%%J\bin\java.exe" set "_EXTRACTED=1"
)

:: Metodo 2: Expand-Archive (PowerShell 5+)
if "!_EXTRACTED!"=="0" call :try_powershell_extract

:: Metodo 3: Shell.Application via VBScript (compativel com Win7+)
::          PS 2.0 nao tem Expand-Archive e Win7 nao tem tar.
if "!_EXTRACTED!"=="0" call :try_vbs_extract

del /F /Q "!CORRETTO_ZIP!" 2>nul

:: Encontra java.exe extraido
for /D %%J in ("%PORTABLE_DIR%\jdk*" "%PORTABLE_DIR%\jre*") do (
    if exist "%%J\bin\java.exe" (
        set "JAVACMD=%%J\bin\java.exe"
        call :log "Corretto 21 portatil instalado em: %%J"
        exit /b 0
    )
)

call :log "[ERRO] Extracao falhou. Estrutura inesperada em: %PORTABLE_DIR%"
exit /b 0

:download
:: Baixa URL %1 para destino %2 com multiplos metodos e output visivel
set "_URL=%~1"
set "_DEST=%~2"
call :log "  URL: !_URL!"
call :log "  Destino: !_DEST!"
if exist "!_DEST!" del /F /Q "!_DEST!" 2>nul

:: 1) PowerShell - habilita TLS 1.2/1.3 via inteiro (3072=Tls12, 12288=Tls13)
::    Nao referencia o enum Tls12 diretamente: em .NET 4.0 esse nome nao existe
::    e a atribuicao via "::Tls12" lanca excecao antes do download.
call :log "  [1] Tentando PowerShell..."
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072 -bor 12288 } catch { try { [Net.ServicePointManager]::SecurityProtocol = 3072 } catch {} }; try { (New-Object Net.WebClient).DownloadFile('!_URL!','!_DEST!'); Write-Host 'OK' } catch { Write-Host ('FAIL: ' + $_.Exception.Message) }"
if exist "!_DEST!" for %%S in ("!_DEST!") do if %%~zS gtr 1000 ( call :log "  Sucesso [%%~zS bytes]" & exit /b 0 )

:: 2) curl (Windows 10+)
call :log "  [2] Tentando curl..."
where curl >nul 2>&1
if not errorlevel 1 (
    curl -L --fail --silent --show-error -o "!_DEST!" "!_URL!"
    if exist "!_DEST!" for %%S in ("!_DEST!") do if %%~zS gtr 1000 ( call :log "  Sucesso [%%~zS bytes]" & exit /b 0 )
)

:: 3) VBScript via MSXML2.XMLHTTP (usa WinINet/IE - suporta TLS 1.2 no Win7
::    SP1 com IE 11 sem precisar de KB de WinHTTP)
call :log "  [3] Tentando VBScript/MSXML..."
call :download_vbs "!_URL!" "!_DEST!"
if exist "!_DEST!" for %%S in ("!_DEST!") do if %%~zS gtr 1000 ( call :log "  Sucesso [%%~zS bytes]" & exit /b 0 )

:: 4) bitsadmin (WinHTTP - so funciona com TLS 1.2 se KB3140245 + reg key)
:: Sem redirect nul: bitsadmin imprime atualizacao de status (bytes transferidos
:: / total + percentual) a cada segundo - serve como barra de progresso pra
:: downloads grandes como Corretto 21 (~200MB). Pra downloads pequenos como JAR
:: (~100KB) aparece so a linha final "Transfer complete".
::
:: Fix (mai/2026): cancela qualquer job 'dl_a3' pendurado de execucao anterior
:: que travou. Usamos nome unico pra nao interferir com outros apps usando BITS.
:: Sem isso, segunda execucao falha com "The requested job is already in use".
call :log "  [4] Tentando bitsadmin (com barra de progresso real-time)..."
bitsadmin /cancel dl_a3 >nul 2>&1
bitsadmin /transfer dl_a3 /priority high "!_URL!" "!_DEST!"
if exist "!_DEST!" for %%S in ("!_DEST!") do if %%~zS gtr 1000 ( call :log "  Sucesso [%%~zS bytes]" & exit /b 0 )

:: 5) certutil (tambem WinHTTP) - sem redirect mostra dots/numbers de progresso
call :log "  [5] Tentando certutil..."
certutil -urlcache -split -f "!_URL!" "!_DEST!"
if exist "!_DEST!" for %%S in ("!_DEST!") do if %%~zS gtr 1000 ( call :log "  Sucesso [%%~zS bytes]" & exit /b 0 )

call :log "  [FALHA] Todos os metodos de download falharam"
call :log "  [DICA] Windows 7: instale o Service Pack 1, IE 11 e o .NET Framework 4.5+"
call :log "         (KB3140245 + Internet Options > Avancadas > marcar TLS 1.2)"
if exist "!_DEST!" del /F /Q "!_DEST!" 2>nul
exit /b 1

:download_vbs
:: Gera VBScript temporario e baixa via MSXML usando WinINet (IE).
:: Tenta msxml3/Microsoft.XMLHTTP primeiro (WinINet -] usa config TLS do IE,
:: que no Win7 SP1 + IE11 tem TLS 1.2 nativo). Se nao houver, cai para
:: msxml6.0 (WinHTTP - exige KB3140245 + reg key no Win7 para TLS 1.2).
set "_VURL=%~1"
set "_VDEST=%~2"
set "_VBS=%TEMP%\_a3dl_%RANDOM%.vbs"
set "_VLOG=%TEMP%\_a3dl_%RANDOM%.log"
> "!_VBS!" echo Option Explicit
>> "!_VBS!" echo Dim http, stream, provider
>> "!_VBS!" echo On Error Resume Next
>> "!_VBS!" echo provider = "MSXML2.XMLHTTP.3.0"
>> "!_VBS!" echo Set http = CreateObject(provider)
>> "!_VBS!" echo If Err.Number ^<^> 0 Or http Is Nothing Then
>> "!_VBS!" echo   Err.Clear
>> "!_VBS!" echo   provider = "Microsoft.XMLHTTP"
>> "!_VBS!" echo   Set http = CreateObject(provider)
>> "!_VBS!" echo End If
>> "!_VBS!" echo If Err.Number ^<^> 0 Or http Is Nothing Then
>> "!_VBS!" echo   Err.Clear
>> "!_VBS!" echo   provider = "MSXML2.XMLHTTP.6.0"
>> "!_VBS!" echo   Set http = CreateObject(provider)
>> "!_VBS!" echo End If
>> "!_VBS!" echo If http Is Nothing Then
>> "!_VBS!" echo   WScript.StdErr.WriteLine "no XMLHTTP provider"
>> "!_VBS!" echo   WScript.Quit 2
>> "!_VBS!" echo End If
>> "!_VBS!" echo WScript.Echo "provider=" ^& provider
>> "!_VBS!" echo http.Open "GET", "!_VURL!", False
>> "!_VBS!" echo If Err.Number ^<^> 0 Then
>> "!_VBS!" echo   WScript.StdErr.WriteLine "Open err " ^& Err.Number ^& " " ^& Err.Description
>> "!_VBS!" echo   WScript.Quit 3
>> "!_VBS!" echo End If
>> "!_VBS!" echo http.Send
>> "!_VBS!" echo If Err.Number ^<^> 0 Then
>> "!_VBS!" echo   WScript.StdErr.WriteLine "Send err " ^& Err.Number ^& " " ^& Err.Description
>> "!_VBS!" echo   WScript.Quit 4
>> "!_VBS!" echo End If
>> "!_VBS!" echo If http.Status ^<^> 200 Then
>> "!_VBS!" echo   WScript.StdErr.WriteLine "HTTP " ^& http.Status
>> "!_VBS!" echo   WScript.Quit 5
>> "!_VBS!" echo End If
>> "!_VBS!" echo Set stream = CreateObject("ADODB.Stream")
>> "!_VBS!" echo If stream Is Nothing Then
>> "!_VBS!" echo   WScript.StdErr.WriteLine "no ADODB.Stream"
>> "!_VBS!" echo   WScript.Quit 6
>> "!_VBS!" echo End If
>> "!_VBS!" echo stream.Type = 1
>> "!_VBS!" echo stream.Open
>> "!_VBS!" echo stream.Write http.responseBody
>> "!_VBS!" echo stream.SaveToFile "!_VDEST!", 2
>> "!_VBS!" echo stream.Close
>> "!_VBS!" echo WScript.Echo "saved"
>> "!_VBS!" echo WScript.Quit 0
cscript //nologo "!_VBS!" > "!_VLOG!" 2>&1
type "!_VLOG!" 2>nul | findstr /v "^$" >> "%LOGFILE%" 2>nul
del /F /Q "!_VBS!" "!_VLOG!" 2>nul
exit /b 0

:check_extracted
:: Verifica se algum jdk*/jre* tem bin\java.exe; se sim, marca _EXTRACTED=1
for /D %%J in ("%PORTABLE_DIR%\jdk*" "%PORTABLE_DIR%\jre*") do (
    if exist "%%J\bin\java.exe" set "_EXTRACTED=1"
)
exit /b 0

:try_powershell_extract
call :log "Tentando extracao via PowerShell..."
powershell -NoProfile -ExecutionPolicy Bypass -Command "Expand-Archive -Path '!CORRETTO_ZIP!' -DestinationPath '%PORTABLE_DIR%' -Force" >nul 2>nul
call :check_extracted
exit /b 0

:try_vbs_extract
call :log "Tentando extracao via Shell.Application/VBScript. Pode levar alguns minutos..."
call :extract_zip_vbs "!CORRETTO_ZIP!" "%PORTABLE_DIR%"
call :check_extracted
exit /b 0

:extract_zip_vbs
:: Extrai um ZIP usando Shell.Application (presente desde Windows XP).
:: Async: poll por bin\java.exe em alguma subpasta de destino, ate 10 min.
set "_ZIP=%~1"
set "_EXDEST=%~2"
set "_EVBS=%TEMP%\_a3ext_%RANDOM%.vbs"
set "_EVLOG=%TEMP%\_a3ext_%RANDOM%.log"
> "!_EVBS!" echo Option Explicit
>> "!_EVBS!" echo Dim sa, srcNs, dstNs, srcItems, fso, attempts, hasJava, folder, entry
>> "!_EVBS!" echo On Error Resume Next
>> "!_EVBS!" echo Set fso = CreateObject("Scripting.FileSystemObject")
>> "!_EVBS!" echo If fso Is Nothing Then WScript.StdErr.WriteLine "no FSO" : WScript.Quit 7
>> "!_EVBS!" echo Set sa = CreateObject("Shell.Application")
>> "!_EVBS!" echo If sa Is Nothing Then WScript.StdErr.WriteLine "no Shell.Application" : WScript.Quit 2
>> "!_EVBS!" echo Set srcNs = sa.NameSpace("!_ZIP!")
>> "!_EVBS!" echo If srcNs Is Nothing Then WScript.StdErr.WriteLine "no zip namespace" : WScript.Quit 3
>> "!_EVBS!" echo Set srcItems = srcNs.Items
>> "!_EVBS!" echo Set dstNs = sa.NameSpace("!_EXDEST!")
>> "!_EVBS!" echo If dstNs Is Nothing Then WScript.StdErr.WriteLine "no dst namespace" : WScript.Quit 4
>> "!_EVBS!" echo WScript.Echo "extracting " ^& srcItems.Count ^& " entries..."
>> "!_EVBS!" echo dstNs.CopyHere srcItems, 16
>> "!_EVBS!" echo attempts = 0
>> "!_EVBS!" echo hasJava = False
>> "!_EVBS!" echo Do
>> "!_EVBS!" echo   WScript.Sleep 2000
>> "!_EVBS!" echo   attempts = attempts + 1
>> "!_EVBS!" echo   Set folder = fso.GetFolder("!_EXDEST!")
>> "!_EVBS!" echo   For Each entry In folder.SubFolders
>> "!_EVBS!" echo     If fso.FileExists(entry.Path ^& "\bin\java.exe") Then
>> "!_EVBS!" echo       hasJava = True
>> "!_EVBS!" echo       Exit For
>> "!_EVBS!" echo     End If
>> "!_EVBS!" echo   Next
>> "!_EVBS!" echo Loop While Not hasJava And attempts ^< 300
>> "!_EVBS!" echo If hasJava Then
>> "!_EVBS!" echo   WScript.Echo "extracted ok"
>> "!_EVBS!" echo   WScript.Quit 0
>> "!_EVBS!" echo Else
>> "!_EVBS!" echo   WScript.StdErr.WriteLine "timeout/no java.exe found"
>> "!_EVBS!" echo   WScript.Quit 5
>> "!_EVBS!" echo End If
cscript //nologo "!_EVBS!" > "!_EVLOG!" 2>&1
type "!_EVLOG!" 2>nul | findstr /v "^$" >> "%LOGFILE%" 2>nul
del /F /Q "!_EVBS!" "!_EVLOG!" 2>nul
exit /b 0

:check_installed
:: Verifica se ASSINADORJAR foi modificado hoje
set "APP_FRESH=0"
if not exist "!ASSINADORJAR!" exit /b 0
if not exist "!DEST!\app\" exit /b 0
:: /D -0 = arquivos modificados hoje. A sintaxe canonica usa o sinal explicito;
:: "/D 0" sem sinal funciona no Windows 10+ mas falha em algumas builds.
:: Wrap em "call" garante que erro de parser do forfiles nao mate o bat host.
call :_run_forfiles
if not errorlevel 1 set "APP_FRESH=1"
exit /b 0

:_run_forfiles
forfiles /P "!DEST!\app" /M "assinadorA3.jar" /D -0 >nul 2>&1
exit /b !errorlevel!

:check_shortcut
:: Verifica se o atalho (.lnk OU .bat de fallback) existe em algum dos caminhos comuns do Desktop.
:: Se nao existir, o instalador completo (jar) precisa rodar para criar.
set "HAS_SHORTCUT=0"
:: Usamos variaveis intermediarias para evitar dupla expansao "if defined X if exist %X%"
:: que pode falhar se %X% contiver caracteres especiais (raros em paths OneDrive corp).
if defined USERPROFILE call :_chk_path "!USERPROFILE!\Desktop"
if defined PUBLIC call :_chk_path "!PUBLIC!\Desktop"
if defined OneDrive call :_chk_path "!OneDrive!\Desktop"
if defined OneDriveConsumer call :_chk_path "!OneDriveConsumer!\Desktop"
if defined OneDriveCommercial call :_chk_path "!OneDriveCommercial!\Desktop"
exit /b 0

:_chk_path
if "%~1"=="" exit /b 0
if not exist "%~1\" exit /b 0
if exist "%~1\AssinadorA3.lnk" call :_validate_lnk "%~1\AssinadorA3.lnk" "%~1"
exit /b 0

:_validate_lnk
:: Valida TargetPath do .lnk via WSH (cscript). Toda a logica de comparacao
:: e feita DENTRO do VBS - assim paths com caracteres especiais como
:: "C:\Program Files (x86)\..." nao precisam ser passados via echoorfindstr,
:: que quebra o parser CMD com parens. O bat so le "VALID" ou outro token.
set "_LNK=%~1"
set "_VBS=%TEMP%\assinadora3_chk_lnk_%RANDOM%.vbs"
> "!_VBS!" echo Dim ws : Set ws = CreateObject("WScript.Shell")
>> "!_VBS!" echo Dim sc : Set sc = ws.CreateShortcut(WScript.Arguments(0))
>> "!_VBS!" echo Dim target : target = sc.TargetPath
>> "!_VBS!" echo Dim dest : dest = WScript.Arguments(1)
>> "!_VBS!" echo If Len(target) = 0 Then
>> "!_VBS!" echo   WScript.Echo "EMPTY"
>> "!_VBS!" echo ElseIf LCase(Left(target, Len(dest))) = LCase(dest) Then
>> "!_VBS!" echo   Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
>> "!_VBS!" echo   If fso.FileExists(target) Then
>> "!_VBS!" echo     WScript.Echo "VALID"
>> "!_VBS!" echo   Else
>> "!_VBS!" echo     WScript.Echo "MISSING"
>> "!_VBS!" echo   End If
>> "!_VBS!" echo Else
>> "!_VBS!" echo   WScript.Echo "OUTSIDE"
>> "!_VBS!" echo End If
set "_LNK_RESULT="
for /f "usebackq delims=" %%T in (`cscript //nologo "!_VBS!" "!_LNK!" "!DEST!" 2^>nul`) do set "_LNK_RESULT=%%T"
del /F /Q "!_VBS!" 2>nul
if "!_LNK_RESULT!"=="VALID" goto :_lnk_valid
if "!_LNK_RESULT!"=="MISSING" goto :_lnk_invalid_missing
if "!_LNK_RESULT!"=="OUTSIDE" goto :_lnk_invalid_outside
goto :_lnk_invalid_unknown

:_lnk_valid
set "HAS_SHORTCUT=1"
exit /b 0

:_lnk_invalid_missing
call :log "  Atalho aponta para alvo inexistente - recriando."
del /F /Q "!_LNK!" 2>nul
exit /b 0

:_lnk_invalid_outside
call :log "  Atalho aponta para fora de DEST - recriando."
del /F /Q "!_LNK!" 2>nul
exit /b 0

:_lnk_invalid_unknown
call :log "  Atalho ilegivel ou status desconhecido - recriando."
del /F /Q "!_LNK!" 2>nul
exit /b 0
