#Requires -Version 5.1
<#
.SYNOPSIS
    FFF MCP Server installer for Windows.
.DESCRIPTION
    Pipe usage:
        irm https://raw.githubusercontent.com/dmtrKovalenko/fff.nvim/main/install-mcp.ps1 | iex
    Direct usage (supports params):
        iwr https://.../install-mcp.ps1 -OutFile install-mcp.ps1; .\install-mcp.ps1 -Version v0.1.2
    Env-var fallbacks (for the piped form):
        $env:FFF_MCP_VERSION, $env:FFF_MCP_INSTALL_DIR
.PARAMETER Version
    Release tag to install (e.g. 'v0.1.2'). Default: latest release containing a Windows MCP asset.
.PARAMETER InstallDir
    Target install directory. Default: $env:LOCALAPPDATA\fff-mcp\bin.
.PARAMETER PathScope
    How to persist PATH: 'User' (set user env var, default), 'Profile' (append to $PROFILE *nix-style), 'None' (do not persist).
    Env-var fallback: $env:FFF_MCP_PATH_SCOPE.
#>
param(
    [string]$Version = $env:FFF_MCP_VERSION,
    [string]$InstallDir = $env:FFF_MCP_INSTALL_DIR,
    [ValidateSet('User', 'Profile', 'None')]
    [string]$PathScope = $(if ($env:FFF_MCP_PATH_SCOPE) { $env:FFF_MCP_PATH_SCOPE } else { 'User' })
)

$ErrorActionPreference = 'Stop'

# Force TLS 1.2 — PS 5.1 on older Win10 may default to SSL3/TLS1.0 which GitHub rejects.
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

$Repo = 'dmtrKovalenko/fff.nvim'
$BinaryName = 'fff-mcp'
if (-not $InstallDir) { $InstallDir = Join-Path $env:LOCALAPPDATA 'fff-mcp\bin' }

function Write-Info    { param($m) Write-Host $m -ForegroundColor Blue }
function Write-Success { param($m) Write-Host $m -ForegroundColor DarkYellow }
function Write-Warn    { param($m) Write-Host $m -ForegroundColor Yellow }

function Get-Target {
    # Read from registry — env vars lie under x86/ARM64 emulation. Same approach Bun uses.
    $arch = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment').PROCESSOR_ARCHITECTURE
    switch ($arch) {
        'AMD64' { return 'x86_64-pc-windows-msvc' }
        'ARM64' { return 'aarch64-pc-windows-msvc' }
        default { throw "Unsupported architecture: $arch" }
    }
}

function Get-LatestReleaseTag {
    param([string]$Target)
    $asset = "$BinaryName-$Target.exe"
    $headers = @{ 'User-Agent' = 'fff-mcp-installer' }
    if ($env:GITHUB_TOKEN) { $headers['Authorization'] = "Bearer $env:GITHUB_TOKEN" }

    $releases = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases" -Headers $headers
    $rel = $releases | Where-Object { $_.assets.name -contains $asset } | Select-Object -First 1
    if (-not $rel) {
        throw "No release found containing $asset. The MCP build may not have been released for this platform yet."
    }
    return $rel.tag_name
}

function Invoke-Download {
    param([string]$Url, [string]$OutFile)
    # curl.exe (ships with Win10 1803+) is faster than iwr on PS 5.1. Fall back to iwr.
    $curl = Get-Command curl.exe -ErrorAction SilentlyContinue
    if ($curl) {
        & $curl.Source -fsSL -o $OutFile $Url
        if ($LASTEXITCODE -ne 0) { throw "curl.exe exited with $LASTEXITCODE" }
    } else {
        $prev = $ProgressPreference
        try {
            # iwr progress bar tanks throughput on PS 5.1.
            $ProgressPreference = 'SilentlyContinue'
            Invoke-WebRequest -Uri $Url -OutFile $OutFile -UseBasicParsing
        } finally {
            $ProgressPreference = $prev
        }
    }
}

function Install-Binary {
    param([string]$Target, [string]$Tag)

    $filename = "$BinaryName-$Target.exe"
    $url = "https://github.com/$Repo/releases/download/$Tag/$filename"

    Write-Info "Downloading $filename from release $Tag..."

    $tmp = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
    New-Item -ItemType Directory -Force -Path $tmp | Out-Null
    try {
        $tmpFile = Join-Path $tmp $filename
        try {
            Invoke-Download -Url $url -OutFile $tmpFile
        } catch {
            Write-Host ""
            Write-Host "Error: Failed to download binary for your platform." -ForegroundColor Red
            Write-Host "  URL: $url"
            Write-Host "  Release: $Tag"
            Write-Host "  Platform: $Target"
            Write-Host "Check available releases at: https://github.com/$Repo/releases"
            throw
        }

        New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
        $dest = Join-Path $InstallDir "$BinaryName.exe"
        Move-Item -Force -Path $tmpFile -Destination $dest
        return $dest
    } finally {
        Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
    }
}

function Test-OnPath {
    param([string]$Dir)
    $paths = $env:PATH -split ';'
    return ($paths -contains $Dir) -or ($paths -contains $Dir.TrimEnd('\'))
}

function Add-ToUserPath {
    param([string]$Dir)
    $userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
    if (-not $userPath) { $userPath = '' }
    $entries = $userPath -split ';' | Where-Object { $_ -ne '' }
    if ($entries -notcontains $Dir) {
        $newPath = (@($entries + $Dir) -join ';')
        [Environment]::SetEnvironmentVariable('Path', $newPath, 'User')
        Write-Success "Added $Dir to user PATH."
    }
}

function Add-ToProfilePath {
    param([string]$Dir)
    $profilePath = $PROFILE.CurrentUserAllHosts
    $line = "`$env:PATH += ';$Dir'  # added by fff-mcp installer"
    if (Test-Path $profilePath) {
        $existing = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue
        if ($existing -and $existing.Contains($Dir)) { return }
    } else {
        New-Item -ItemType File -Force -Path $profilePath | Out-Null
    }
    Add-Content -Path $profilePath -Value "`n$line"
    Write-Success "Appended PATH update to $profilePath."
}

function Set-Path {
    param([string]$Dir, [string]$Scope)
    switch ($Scope) {
        'User'    { Add-ToUserPath $Dir }
        'Profile' { Add-ToProfilePath $Dir }
        'None'    { Write-Info "Skipping PATH persistence (-PathScope None)." }
    }
    # Make available in current session regardless of scope.
    if (-not (Test-OnPath $Dir)) { $env:PATH = "$env:PATH;$Dir" }
}

function Show-SetupInstructions {
    param([string]$BinaryPath)
    $foundAny = $false

    Write-Host ""
    Write-Success "FFF MCP Server installed successfully!"
    Write-Host ""
    Write-Info "Setup with your AI coding assistant:"
    Write-Host ""

    if (Get-Command claude -ErrorAction SilentlyContinue) {
        $foundAny = $true
        Write-Success "[Claude Code] detected"
        Write-Host ""
        Write-Host "Global (recommended):"
        Write-Host "claude mcp add -s user fff -- $BinaryPath"
        Write-Host ""
        Write-Host "Or project-level .mcp.json (uses PATH):"
        Write-Host @'
{
  "mcpServers": {
    "fff": {
      "type": "stdio",
      "command": "fff-mcp",
      "args": []
    }
  }
}
'@
        Write-Host ""
    }

    if (Get-Command opencode -ErrorAction SilentlyContinue) {
        $foundAny = $true
        Write-Success "[OpenCode] detected"
        Write-Host "Add to your opencode.json:"
        Write-Host @'
{
  "mcp": {
    "fff": {
      "type": "local",
      "command": ["fff-mcp"],
      "enabled": true
    }
  }
}
'@
        Write-Host ""
    }

    if (Get-Command codex -ErrorAction SilentlyContinue) {
        $foundAny = $true
        Write-Success "[Codex] detected"
        Write-Host "codex mcp add fff -- `"$BinaryPath`""
        Write-Host ""
    }

    if (-not $foundAny) {
        Write-Host "No AI coding assistants detected."
        Write-Host "Binary path: $BinaryPath"
        Write-Host ""
    }

    Write-Host "Binary: $BinaryPath"
    Write-Host "Docs:   https://github.com/$Repo"
    Write-Host ""
    Write-Info "Tip: Add this to your CLAUDE.md or AGENTS.md to make AI use fff for all searches:"
    Write-Host '"Use the fff MCP tools for all file search operations instead of default tools."'
}

function Main {
    $target = Get-Target

    $existing = Join-Path $InstallDir "$BinaryName.exe"
    $isUpdate = Test-Path $existing

    if ($isUpdate) {
        Write-Info "Updating FFF MCP Server..."
    } else {
        Write-Info "Installing FFF MCP Server..."
    }
    Write-Host ""
    Write-Info "Detected platform: $target"

    if ($Version) {
        $tag = $Version
        Write-Info "Using pinned version: $tag"
    } else {
        $tag = Get-LatestReleaseTag -Target $target
    }
    $binaryPath = Install-Binary -Target $target -Tag $tag

    if ($isUpdate) {
        Write-Host ""
        Write-Success "FFF MCP Server updated to $tag!"
        Write-Host ""
    } else {
        Set-Path -Dir $InstallDir -Scope $PathScope
        Show-SetupInstructions -BinaryPath $binaryPath
    }
}

Main
