# ═══════════════════════════════════════════════════════════════════════════════
# Lumo CLI + Skill Installer for Windows
#
# Usage: extract the release bundle (LumoCLI-windows-<arch>.zip) and
#        double-click install.bat (which invokes this script).
#
# Flags:
#   --no-skill                         skip skill installation
#   --skill-target auto|all|claude|codex|opencode|cursor|claude,codex,cursor
# ═══════════════════════════════════════════════════════════════════════════════

param([switch]$NoSkill)

$SkillTarget = "auto"
for ($i = 0; $i -lt $args.Count; $i++) {
    $arg = [string]$args[$i]
    if ($arg -eq "--no-skill") {
        $NoSkill = $true
    } elseif ($arg -eq "--skill-target") {
        $i++
        if ($i -ge $args.Count) {
            Write-Host "Error: --skill-target requires a value: auto, all, claude, codex, opencode, cursor, or a comma-separated combination" -ForegroundColor Red
            exit 1
        }
        $SkillTarget = [string]$args[$i]
    } elseif ($arg.StartsWith("--skill-target=")) {
        $SkillTarget = $arg.Substring("--skill-target=".Length)
    } else {
        Write-Host "Error: unknown flag: $arg" -ForegroundColor Red
        exit 1
    }
}

$ErrorActionPreference = "Stop"

$InstallDir  = Join-Path $env:LOCALAPPDATA "Lumo"
$InstalledSkillAgents = @()

# ─── Helpers ──────────────────────────────────────────────────────────────────

function Write-Step  ($msg) { Write-Host "  [*] " -NoNewline -ForegroundColor Cyan;    Write-Host $msg }
function Write-Ok    ($msg) { Write-Host "  [+] " -NoNewline -ForegroundColor Green;   Write-Host $msg }
function Write-Warn  ($msg) { Write-Host "  [!] " -NoNewline -ForegroundColor Yellow;  Write-Host $msg }
function Write-Fail  ($msg) { Write-Host "  [-] " -NoNewline -ForegroundColor Red;     Write-Host $msg }

function Test-AgentInstalled($Name) {
    switch ($Name) {
        "claude" {
            return (([bool](Get-Command claude -ErrorAction SilentlyContinue)) -or
                (Test-Path (Join-Path $env:USERPROFILE ".claude")))
        }
        "codex" {
            return (([bool](Get-Command codex -ErrorAction SilentlyContinue)) -or
                (Test-Path (Join-Path $env:USERPROFILE ".codex")) -or
                (Test-Path (Join-Path $env:USERPROFILE ".agents")))
        }
        "opencode" {
            return (([bool](Get-Command opencode -ErrorAction SilentlyContinue)) -or
                (Test-Path (Join-Path $env:USERPROFILE ".config\opencode")))
        }
        "cursor" {
            return (([bool](Get-Command cursor -ErrorAction SilentlyContinue)) -or
                ([bool](Get-Command cursor-agent -ErrorAction SilentlyContinue)) -or
                (Test-Path (Join-Path $env:USERPROFILE ".cursor")))
        }
        default { return $false }
    }
}

function Get-SkillTargets($Target) {
    $normalized = $Target.ToLowerInvariant()
    if ($normalized -eq "auto") {
        $targets = @()
        $covered = $false
        if (Test-AgentInstalled "claude")   { $targets += "claude";   $covered = $true }
        if (Test-AgentInstalled "codex")    { $targets += "codex";    $covered = $true }
        if (Test-AgentInstalled "opencode") { $targets += "opencode" }
        # O Cursor le ~/.claude/skills e ~/.agents/skills como caminhos de
        # compatibilidade: se um deles ja recebeu, instalar em ~/.cursor/skills
        # faria o Cursor carregar a mesma skill duas vezes. OpenCode nao conta,
        # o Cursor nunca le a pasta dele.
        if ((-not $covered) -and (Test-AgentInstalled "cursor")) { $targets += "cursor" }
        return $targets
    }
    if ($normalized -eq "all") {
        return @("claude", "codex", "opencode", "cursor")
    }
    return $normalized.Split(",") | ForEach-Object { $_.Trim() } | Where-Object { $_ }
}

function Install-SkillTo($AgentName, $DestDir, $LocalSkillDir) {
    # Legacy cleanup - older installs wrote to .../skills/lumo (no -cli).
    # If both names exist, the agent loads two skills with conflicting
    # content, so always sweep the legacy path first.
    $LegacyDir = $DestDir -replace 'lumo-cli$', 'lumo'
    if ($LegacyDir -ne $DestDir -and (Test-Path $LegacyDir)) {
        Remove-Item -Recurse -Force $LegacyDir -ErrorAction SilentlyContinue
    }

    # Remove the current skill directory before writing the new one. The
    # failure mode this guards against: if the agent (Claude Code, Codex)
    # is running, it holds SKILL.md mmap'd; Remove-Item / Copy-Item then
    # fail with "Access is denied" and the user ends up with stale files
    # AND no clear error. Surface a precise message telling them what to
    # close, then bail rather than continuing with half-applied files.
    if (Test-Path $DestDir) {
        try {
            Remove-Item -Recurse -Force $DestDir -ErrorAction Stop
        } catch {
            Write-Warn "Nao foi possivel remover '$DestDir' (provavel arquivo em uso pelo $AgentName)."
            Write-Host "      Feche o $AgentName e todo terminal com 'lumo' aberto," -ForegroundColor Yellow
            Write-Host "      depois rode o instalador novamente." -ForegroundColor Yellow
            throw "Skill ($AgentName) nao atualizada - arquivos em uso"
        }
    }
    New-Item -ItemType Directory -Path $DestDir -Force | Out-Null

    try {
        Copy-Item (Join-Path $LocalSkillDir "SKILL.md") $DestDir -Force -ErrorAction Stop
        # Copia TODO subdiretorio da skill, nao uma lista fixa. A lista fixa
        # (references + scripts) deixou de fora assets/ da lumo-mockup, que
        # carrega as fontes exigidas em runtime: sem elas o render sai sem
        # nenhum rotulo e sem erro. Iterar evita repetir esse esquecimento a
        # cada subdiretorio novo.
        Get-ChildItem -Path $LocalSkillDir -Directory -ErrorAction SilentlyContinue | ForEach-Object {
            Copy-Item $_.FullName $DestDir -Recurse -Force -ErrorAction Stop
        }
    } catch {
        Write-Warn "Falha ao copiar arquivos da skill para '$DestDir': $($_.Exception.Message)"
        Write-Host "      Confira se nenhum arquivo da skill esta aberto e rode novamente." -ForegroundColor Yellow
        throw "Skill ($AgentName) nao atualizada - copia falhou"
    }
    Write-Ok "Skill ($AgentName): $DestDir"
}

# ─── Banner ───────────────────────────────────────────────────────────────────

Write-Host ""
Write-Host "  ╔══════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "  ║                                              ║" -ForegroundColor Cyan
Write-Host "  ║        Lumo CLI - Instalador Windows         ║" -ForegroundColor Cyan
Write-Host "  ║        Horus BI Platform                     ║" -ForegroundColor Cyan
Write-Host "  ║                                              ║" -ForegroundColor Cyan
Write-Host "  ╚══════════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""
Write-Host "  IMPORTANTE: feche o Claude Code, Codex, Cursor e qualquer terminal" -ForegroundColor Yellow
Write-Host "  com 'lumo' aberto antes de continuar. Arquivos em uso nao" -ForegroundColor Yellow
Write-Host "  podem ser sobrescritos no Windows e a atualizacao falha em" -ForegroundColor Yellow
Write-Host "  silencio (a skill ou o binario fica com a versao antiga)." -ForegroundColor Yellow
Write-Host ""

# ─── Locate bundle files ──────────────────────────────────────────────────────

$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ParentDir = Split-Path -Parent $ScriptDir

$LocalBinary = Join-Path $ScriptDir "lumo.exe"
$BundleDir   = $ScriptDir
if (-not (Test-Path $LocalBinary)) {
    $LocalBinary = Join-Path $ParentDir "lumo.exe"
    if (Test-Path $LocalBinary) { $BundleDir = $ParentDir }
}

if (-not (Test-Path $LocalBinary)) {
    Write-Fail "Binario 'lumo.exe' nao encontrado ao lado do install.bat nem na pasta pai."
    Write-Host ""
    Write-Host "  Este instalador funciona apenas a partir do bundle de release extraido."
    Write-Host "  Baixe LumoCLI-windows-amd64.zip em:"
    Write-Host "    https://gitlab.horusdev.com.br/horus/lumo-cli/-/releases"
    Write-Host "  Extraia o zip e execute install.bat de dentro da pasta extraida."
    Write-Host ""
    exit 1
}

$LocalSkill       = Join-Path $BundleDir "skill\SKILL.md"
$LocalSkillDesign = Join-Path $BundleDir "skill-design\SKILL.md"
$LocalSkillDecks  = Join-Path $BundleDir "skill-decks\SKILL.md"
$LocalSkillScope  = Join-Path $BundleDir "skill-scope\SKILL.md"
$LocalSkillMockup = Join-Path $BundleDir "skill-mockup\SKILL.md"

$Arch = if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "amd64" }
Write-Step "Plataforma: Windows $Arch"
Write-Host ""

$Tmp = Join-Path $env:TEMP ("lumo-install-" + (Get-Random))
New-Item -ItemType Directory -Path $Tmp -Force | Out-Null

try {

Write-Step "Copiando lumo.exe do pacote..."
Copy-Item $LocalBinary "$Tmp\lumo.exe" -Force

# ─── Install binary ──────────────────────────────────────────────────────────

Write-Step "Instalando CLI..."
if (!(Test-Path $InstallDir)) {
    New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
}
Copy-Item "$Tmp\lumo.exe" "$InstallDir\lumo.exe" -Force
Write-Ok "CLI: $InstallDir\lumo.exe"

# ─── Remove stray copies on PATH (avoid v1+v2 coexistence) ─────────────────
# If a previous version was installed at a different path (custom dir,
# Chocolatey, manual placement) we'd leave both `.exe` files on disk and
# let PATH order decide which one runs. Walk the user+system PATH and
# remove any stale `lumo.exe` we find, leaving only ours.
$TargetExe = Join-Path $InstallDir "lumo.exe"
$PathDirs = @()
$PathDirs += ([Environment]::GetEnvironmentVariable("Path", "User") -split ';')
$PathDirs += ([Environment]::GetEnvironmentVariable("Path", "Machine") -split ';')
$PathDirs = $PathDirs | Where-Object { $_ -and (Test-Path $_) } | Select-Object -Unique
foreach ($Dir in $PathDirs) {
    $Candidate = Join-Path $Dir "lumo.exe"
    if (-not (Test-Path $Candidate)) { continue }
    if ((Resolve-Path $Candidate).Path -ieq (Resolve-Path $TargetExe).Path) { continue }
    try {
        Remove-Item -Force $Candidate -ErrorAction Stop
        Write-Host "      Removido binario antigo: $Candidate" -ForegroundColor DarkGray
    } catch {
        Write-Warn "Nao foi possivel remover $Candidate - remova manualmente"
    }
}

# ─── Add to PATH ─────────────────────────────────────────────────────────────

Write-Step "Configurando PATH..."
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($UserPath -like "*$InstallDir*") {
    Write-Ok "PATH ja configurado"
} else {
    try {
        [Environment]::SetEnvironmentVariable("Path", "$InstallDir;$UserPath", "User")
        $env:Path = "$InstallDir;$env:Path"
        Write-Ok "Adicionado ao PATH"
    } catch {
        Write-Warn "Nao foi possivel modificar o PATH"
        Write-Host "      Adicione manualmente: $InstallDir" -ForegroundColor DarkGray
    }
}

# ─── Install skill ───────────────────────────────────────────────────────────

if (-not $NoSkill) {
    Write-Host ""
    Write-Step "Instalando skills para agentes detectados..."

    if (-not (Test-Path $LocalSkill)) {
        Write-Warn "skill/SKILL.md nao encontrado no pacote - pulando instalacao da skill"
    } else {
        $LocalSkillDir = Split-Path -Parent $LocalSkill
        $Targets = @(Get-SkillTargets $SkillTarget | Select-Object -Unique)

        if ($Targets.Count -eq 0) {
            Write-Warn "Nenhum agente suportado detectado (Claude Code, Codex, OpenCode ou Cursor); pulando skill"
            Write-Host "      Use --skill-target all para forcar instalacao em todas as pastas conhecidas." -ForegroundColor DarkGray
        } else {
            foreach ($Target in $Targets) {
                switch ($Target) {
                    "claude" {
                        $Dest = Join-Path $env:USERPROFILE ".claude\skills\lumo-cli"
                        Install-SkillTo "Claude Code" $Dest $LocalSkillDir
                        # Install lumo-design skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDesign) {
                            $DesignDest = Join-Path $env:USERPROFILE ".claude\skills\lumo-design"
                            $LocalSkillDesignDir = Split-Path -Parent $LocalSkillDesign
                            Install-SkillTo "Claude Code (lumo-design)" $DesignDest $LocalSkillDesignDir
                        }
                        # Install lumo-decks skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDecks) {
                            $DecksDest = Join-Path $env:USERPROFILE ".claude\skills\lumo-decks"
                            $LocalSkillDecksDir = Split-Path -Parent $LocalSkillDecks
                            Install-SkillTo "Claude Code (lumo-decks)" $DecksDest $LocalSkillDecksDir
                        }
                        # Install lumo-scope skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillScope) {
                            $ScopeDest = Join-Path $env:USERPROFILE ".claude\skills\lumo-scope"
                            $LocalSkillScopeDir = Split-Path -Parent $LocalSkillScope
                            Install-SkillTo "Claude Code (lumo-scope)" $ScopeDest $LocalSkillScopeDir
                        }
                        # Install lumo-mockup skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillMockup) {
                            $MockupDest = Join-Path $env:USERPROFILE ".claude\skills\lumo-mockup"
                            $LocalSkillMockupDir = Split-Path -Parent $LocalSkillMockup
                            Install-SkillTo "Claude Code (lumo-mockup)" $MockupDest $LocalSkillMockupDir
                        }
                        $InstalledSkillAgents += "Claude Code"
                    }
                    "codex" {
                        $Dest = Join-Path $env:USERPROFILE ".agents\skills\lumo-cli"
                        Install-SkillTo "Codex" $Dest $LocalSkillDir
                        # Install lumo-design skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDesign) {
                            $DesignDest = Join-Path $env:USERPROFILE ".agents\skills\lumo-design"
                            $LocalSkillDesignDir = Split-Path -Parent $LocalSkillDesign
                            Install-SkillTo "Codex (lumo-design)" $DesignDest $LocalSkillDesignDir
                        }
                        # Install lumo-decks skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDecks) {
                            $DecksDest = Join-Path $env:USERPROFILE ".agents\skills\lumo-decks"
                            $LocalSkillDecksDir = Split-Path -Parent $LocalSkillDecks
                            Install-SkillTo "Codex (lumo-decks)" $DecksDest $LocalSkillDecksDir
                        }
                        # Install lumo-scope skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillScope) {
                            $ScopeDest = Join-Path $env:USERPROFILE ".agents\skills\lumo-scope"
                            $LocalSkillScopeDir = Split-Path -Parent $LocalSkillScope
                            Install-SkillTo "Codex (lumo-scope)" $ScopeDest $LocalSkillScopeDir
                        }
                        # Install lumo-mockup skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillMockup) {
                            $MockupDest = Join-Path $env:USERPROFILE ".agents\skills\lumo-mockup"
                            $LocalSkillMockupDir = Split-Path -Parent $LocalSkillMockup
                            Install-SkillTo "Codex (lumo-mockup)" $MockupDest $LocalSkillMockupDir
                        }
                        $InstalledSkillAgents += "Codex"
                    }
                    "opencode" {
                        $Dest = Join-Path $env:USERPROFILE ".config\opencode\skills\lumo-cli"
                        Install-SkillTo "OpenCode" $Dest $LocalSkillDir
                        # Install lumo-design skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDesign) {
                            $DesignDest = Join-Path $env:USERPROFILE ".config\opencode\skills\lumo-design"
                            $LocalSkillDesignDir = Split-Path -Parent $LocalSkillDesign
                            Install-SkillTo "OpenCode (lumo-design)" $DesignDest $LocalSkillDesignDir
                        }
                        # Install lumo-decks skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDecks) {
                            $DecksDest = Join-Path $env:USERPROFILE ".config\opencode\skills\lumo-decks"
                            $LocalSkillDecksDir = Split-Path -Parent $LocalSkillDecks
                            Install-SkillTo "OpenCode (lumo-decks)" $DecksDest $LocalSkillDecksDir
                        }
                        # Install lumo-scope skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillScope) {
                            $ScopeDest = Join-Path $env:USERPROFILE ".config\opencode\skills\lumo-scope"
                            $LocalSkillScopeDir = Split-Path -Parent $LocalSkillScope
                            Install-SkillTo "OpenCode (lumo-scope)" $ScopeDest $LocalSkillScopeDir
                        }
                        # Install lumo-mockup skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillMockup) {
                            $MockupDest = Join-Path $env:USERPROFILE ".config\opencode\skills\lumo-mockup"
                            $LocalSkillMockupDir = Split-Path -Parent $LocalSkillMockup
                            Install-SkillTo "OpenCode (lumo-mockup)" $MockupDest $LocalSkillMockupDir
                        }
                        $InstalledSkillAgents += "OpenCode"
                    }
                    "cursor" {
                        $Dest = Join-Path $env:USERPROFILE ".cursor\skills\lumo-cli"
                        Install-SkillTo "Cursor" $Dest $LocalSkillDir
                        # Install lumo-design skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDesign) {
                            $DesignDest = Join-Path $env:USERPROFILE ".cursor\skills\lumo-design"
                            $LocalSkillDesignDir = Split-Path -Parent $LocalSkillDesign
                            Install-SkillTo "Cursor (lumo-design)" $DesignDest $LocalSkillDesignDir
                        }
                        # Install lumo-decks skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillDecks) {
                            $DecksDest = Join-Path $env:USERPROFILE ".cursor\skills\lumo-decks"
                            $LocalSkillDecksDir = Split-Path -Parent $LocalSkillDecks
                            Install-SkillTo "Cursor (lumo-decks)" $DecksDest $LocalSkillDecksDir
                        }
                        # Install lumo-scope skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillScope) {
                            $ScopeDest = Join-Path $env:USERPROFILE ".cursor\skills\lumo-scope"
                            $LocalSkillScopeDir = Split-Path -Parent $LocalSkillScope
                            Install-SkillTo "Cursor (lumo-scope)" $ScopeDest $LocalSkillScopeDir
                        }
                        # Install lumo-mockup skill when present in bundle (absent in old bundles).
                        if (Test-Path $LocalSkillMockup) {
                            $MockupDest = Join-Path $env:USERPROFILE ".cursor\skills\lumo-mockup"
                            $LocalSkillMockupDir = Split-Path -Parent $LocalSkillMockup
                            Install-SkillTo "Cursor (lumo-mockup)" $MockupDest $LocalSkillMockupDir
                        }
                        $InstalledSkillAgents += "Cursor"
                    }
                    default {
                        throw "Unknown skill target '$Target' - supported: auto, all, claude, codex, opencode, cursor."
                    }
                }
            }
        }
    }
}

# ─── Verify ───────────────────────────────────────────────────────────────────

Write-Step "Verificando..."
try {
    $ver = & "$InstallDir\lumo.exe" version 2>&1
    Write-Ok "CLI funcionando: $ver"
} catch {
    Write-Ok "CLI instalado (abra um novo terminal para usar)"
}

# ─── Summary ──────────────────────────────────────────────────────────────────

Write-Host ""
Write-Host "  ╔══════════════════════════════════════════════╗" -ForegroundColor Green
Write-Host "  ║        Instalacao concluida!                 ║" -ForegroundColor Green
Write-Host "  ╚══════════════════════════════════════════════╝" -ForegroundColor Green
Write-Host ""
Write-Host "  Proximos passos:" -ForegroundColor White
Write-Host "    1. Abra um NOVO terminal" -ForegroundColor Yellow
Write-Host "    2. lumo auth login" -ForegroundColor Gray
Write-Host "    3. lumo auth status" -ForegroundColor Gray
if (-not $NoSkill) {
    if ($InstalledSkillAgents.Count -gt 0) {
        Write-Host "    4. Reinicie: $($InstalledSkillAgents -join ', ')" -ForegroundColor Yellow
    }
}
Write-Host ""

} catch {
    Write-Host ""
    Write-Fail "Erro: $($_.Exception.Message)"
    Write-Host ""
    exit 1
} finally {
    Remove-Item -Recurse -Force $Tmp -ErrorAction SilentlyContinue
}
