$ErrorActionPreference = "Stop"

Set-Location -LiteralPath $PSScriptRoot

function Wait-ToClose {
  Write-Host ""
  Read-Host "Press Enter to close this window" | Out-Null
}

function Fail($message) {
  Write-Host ""
  Write-Host "ERROR: $message" -ForegroundColor Red
  Wait-ToClose
  exit 1
}

function Info($message) { Write-Host $message -ForegroundColor Cyan }
function Success($message) { Write-Host $message -ForegroundColor Green }

function PlainTextFromSecureString($secure) {
  $ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure)
  try { [Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr) } finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr) }
}

function Get-EnvValue($name) {
  if (-not (Test-Path -LiteralPath ".env")) { return "" }
  $line = Get-Content -LiteralPath ".env" | Where-Object { $_ -match "^\s*$name\s*=" } | Select-Object -Last 1
  if (-not $line) { return "" }
  return (($line -split "=", 2)[1]).Trim()
}

function Set-EnvValue($name, $value) {
  $lines = @()
  if (Test-Path -LiteralPath ".env") { $lines = @(Get-Content -LiteralPath ".env") }
  $found = $false
  $next = foreach ($line in $lines) {
    if ($line -match "^\s*$name\s*=") {
      $found = $true
      "$name=$value"
    } else {
      $line
    }
  }
  if (-not $found) { $next += "$name=$value" }
  Set-Content -LiteralPath ".env" -Value $next -Encoding UTF8
}

function Ensure-PrivateKey($name, $label) {
  $current = Get-EnvValue $name
  if ($current) { return }
  Write-Host ""
  Info "First-time setup: paste the private key for this dedicated $label wallet."
  Write-Host "Do not use your main wallet." -ForegroundColor Yellow
  do {
    $secure = Read-Host "Private key" -AsSecureString
    $plain = (PlainTextFromSecureString $secure).Trim()
  } while (-not $plain)
  Set-EnvValue $name $plain
  Success "$name saved to .env."
}

try {
  Write-Host ""
  Write-Host "3SAT Solver Client for Windows" -ForegroundColor White
  Write-Host "==============================" -ForegroundColor White
  Write-Host ""

  if (-not (Test-Path -LiteralPath ".env")) {
    if (-not (Test-Path -LiteralPath ".env.example")) { Fail ".env.example was not found." }
    Copy-Item -LiteralPath ".env.example" -Destination ".env"
    Info "Created .env from .env.example."
  }
  Ensure-PrivateKey "SOLVER_PRIVATE_KEY" "solver"

  if (-not (Get-Command node -ErrorAction SilentlyContinue)) { Fail "Node.js was not found. Install Node.js LTS from https://nodejs.org, then run this file again." }
  if (-not (Get-Command npm -ErrorAction SilentlyContinue)) { Fail "npm was not found. Install Node.js LTS from https://nodejs.org, then run this file again." }
  if (-not (Test-Path -LiteralPath "bin\cryptominisat5.exe")) { Fail "bin\cryptominisat5.exe was not found. Put the bundled CryptoMiniSat binary back under bin\." }

  Info "Checking CryptoMiniSat..."
  $smokeCnf = Join-Path $env:TEMP "3sat-solver-smoke.cnf"
  Set-Content -LiteralPath $smokeCnf -Value @("p cnf 2 2", "1 2 0", "-1 2 0") -Encoding ASCII
  $solverOutput = & ".\bin\cryptominisat5.exe" --verb 0 $smokeCnf 2>&1
  if (($solverOutput -join "`n") -notmatch "SATISFIABLE") { Fail "CryptoMiniSat did not return SATISFIABLE in the smoke test. Output: $solverOutput" }
  Success "CryptoMiniSat works."

  if (-not (Test-Path -LiteralPath "node_modules")) {
    Info "Installing Node dependencies. This runs only on first setup or after node_modules is deleted."
    npm install
    if ($LASTEXITCODE -ne 0) { Fail "npm install failed." }
  }

  Info "Building solver client..."
  npm run build
  if ($LASTEXITCODE -ne 0) { Fail "TypeScript build failed." }

  Success "Starting solver. Press Ctrl+C to stop it."
  Write-Host ""
  npm run start
  if ($LASTEXITCODE -ne 0) { Fail "Solver client stopped with an error. Check logs\solver-client.log for details." }
  Success "Solver client stopped."
  Wait-ToClose
} catch {
  Fail $_.Exception.Message
}
