param(
    [switch]$PDF,
    [switch]$SkipDeps,
    [switch]$Uninstall,
    [ValidateSet('ja','en')]
    [string]$Language = 'ja'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function Write-Info($m){ Write-Host "[INFO] $m" -ForegroundColor Cyan }
function Write-Warn($m){ Write-Host "[WARN] $m" -ForegroundColor Yellow }
function Write-Err($m){ Write-Host "[ERROR] $m" -ForegroundColor Red }

$Root = Split-Path -Parent $PSCommandPath
Set-Location -Path $Root

$ExeMain = Join-Path $Root 'Claude_ASA.exe'
$HasExe = (Test-Path -LiteralPath $ExeMain)

function Write-Utf8NoBom {
  param(
    [Parameter(Mandatory=$true)][string]$Path,
    [Parameter(Mandatory=$true)][string]$Text
  )
  $enc = New-Object System.Text.UTF8Encoding($false)
  [System.IO.File]::WriteAllText($Path, $Text, $enc)
}

function Get-AppInstallId {
  param([Parameter(Mandatory=$true)][string]$Dir)
  $fullPath = [System.IO.Path]::GetFullPath($Dir)
  $name = [System.IO.Path]::GetFileName($fullPath)
  $base = [regex]::Replace($name, '[^A-Za-z0-9._-]+', '_').Trim('._-')
  if (-not $base) { $base = 'install' }
  $bytes = [System.Text.Encoding]::UTF8.GetBytes($fullPath)
  $sha = [System.Security.Cryptography.SHA1]::Create()
  $hash = $sha.ComputeHash($bytes)
  $h = [System.BitConverter]::ToString($hash[0..3]).Replace('-','').ToLower()
  return "${base}_${h}"
}

function Set-LanguagePreference {
  param([Parameter(Mandatory=$true)][ValidateSet('ja','en')][string]$Lang)
  try {
    if ($HasExe) {
      # PL-131: 設定は版ごとの共有 dir に置く (インストール場所に依存させない)。
      # 以前は installs\<パスハッシュ>\ 配下で、展開先が変わるたびに設定が失われた。
      # Python側 data_dir() と同じ規則。TEST 配布は .test マーカーで分離する。
      # NOTE: NMH manifest は per-install のままが正しい (Get-NmhManifestPath 参照)。
      $localAppData = $env:LOCALAPPDATA
      if (-not $localAppData) { return }
      $dir = Join-Path $localAppData 'Claude_ASA'
      if (Test-Path -LiteralPath (Join-Path $Root '.test')) { $dir = Join-Path $dir 'test' }
      $path = Join-Path $dir 'settings.json'
    } else {
      $dir = $Root
      $path = Join-Path $dir 'settings.json'
    }
    if (-not (Test-Path -LiteralPath $dir)) {
      New-Item -ItemType Directory -Path $dir -Force | Out-Null
    }
    $data = @{}
    if (Test-Path -LiteralPath $path) {
      try {
        # PL-131: -Encoding UTF8 は必須。 PS 5.1 の Get-Content は既定で ANSI
        # (日本語環境では cp932) として読むため、 UTF-8 の settings.json に日本語
        # (タグ名など) が入っていると文字化けして JSON 解析に失敗する。
        # 旧実装はその失敗を catch で握りつぶして $data を空にし、 LANGUAGE だけの
        # ファイルを書き戻していた = **セットアップのたびに全設定が消える**。
        $raw = Get-Content -LiteralPath $path -Raw -Encoding UTF8 -ErrorAction Stop
        $parsed = $raw | ConvertFrom-Json -ErrorAction Stop
        $data = @{}
        $parsed.PSObject.Properties | ForEach-Object { $data[$_.Name] = $_.Value }
      } catch {
        # PL-131: 読めなかった設定を空扱いで上書きしない。 言語の保存を諦める方が、
        # ユーザーの設定を消すより無害 (言語は設定画面から変更できる)。
        Write-Warn "既存 settings.json を読めませんでした。設定を保護するため言語の保存を skip します: $path"
        return
      }
    }
    $data['LANGUAGE'] = $Lang
    $json = $data | ConvertTo-Json -Depth 20
    Write-Utf8NoBom -Path $path -Text $json
    Write-Info "言語設定を保存: $Lang -> $path"
  } catch { }
}

# NMH (Native Messaging Host) 定数 (PL-018 CP5)
# PL-072: TEST 配布は .test marker で自己識別し、本番と別 host 名 + 別 registry key +
# 固定鍵 test 拡張 ID のみを許可する。本番 install と同時並存しても混線しない。
$IsTest = Test-Path -LiteralPath (Join-Path $Root '.test')
if ($IsTest) {
  Write-Info 'TEST 配布を検出 (.test marker)。test 系統として NMH を登録します。'
  $NmhHostName = 'com.asa.claude_nmh_test'
  $NmhDescription = 'ASA Bridge for Claude (TEST) - Native Messaging Host (spawns the TEST Claude_ASA on widget click).'
  # allowed_origins: 固定鍵 test 拡張 ID のみ (展開場所に依存しない安定 ID)
  $NmhAllowedOrigins = @(
    'chrome-extension://clecobcjejfedddolkmdlfadfaoegjpa/'
  )
} else {
  $NmhHostName = 'com.asa.claude_nmh'
  $NmhDescription = 'ASA Bridge for Claude - Native Messaging Host (spawns Claude_ASA on widget click).'
  # allowed_origins: 配布 ID + dev unpacked ID (CP6 で dev ID 除去予定)
  $NmhAllowedOrigins = @(
    'chrome-extension://hicmfifjeljeanfdejhhfinnloobnjla/',
    'chrome-extension://olfkjcibhhijaohadokibmiijggehoek/'
  )
}
$NmhRegistryKey = "HKCU:\Software\Google\Chrome\NativeMessagingHosts\$NmhHostName"

function Get-NmhManifestPath {
  if ($HasExe) {
    $localAppData = $env:LOCALAPPDATA
    if (-not $localAppData) { return $null }
    $installId = Get-AppInstallId -Dir $Root
    $dir = Join-Path $localAppData "Claude_ASA\installs\$installId"
    if (-not (Test-Path -LiteralPath $dir)) {
      New-Item -ItemType Directory -Path $dir -Force | Out-Null
    }
    return (Join-Path $dir "$NmhHostName.json")
  } else {
    return (Join-Path $Root "$NmhHostName.json")
  }
}

function Get-NmhHelperPath {
  # PL-073: 配布 App は平坦化されるため App\nmh_helper_claude\ を参照 (旧 build_exe\dist\ は配布に存在しない)。
  if ($HasExe) {
    return (Join-Path $Root 'nmh_helper_claude\nmh_helper_claude.exe')
  } else {
    $repoRoot = Split-Path -Parent $Root
    return (Join-Path $repoRoot 'tools\nmh_helper_claude.bat')
  }
}

function Register-NmhHost {
  $manifestPath = Get-NmhManifestPath
  if (-not $manifestPath) {
    Write-Warn 'NMH manifest 配置先決定不可 (LOCALAPPDATA 未定義)。NMH 登録 skip。'
    return
  }
  $helperPath = Get-NmhHelperPath
  if (-not (Test-Path -LiteralPath $helperPath)) {
    Write-Warn "NMH helper 不在: $helperPath"
    Write-Warn 'EXE 配布の場合 build_exe/dist/nmh_helper_claude/ 配下に nmh_helper_claude.exe を配置してください。source 配布の場合 monorepo の tools/nmh_helper_claude.bat を確認してください。'
    Write-Warn 'NMH manifest は生成されますが、widget 起動経路は機能しません。'
  }
  $obj = [ordered]@{
    name = $NmhHostName
    description = $NmhDescription
    path = $helperPath
    type = 'stdio'
    allowed_origins = $NmhAllowedOrigins
  }
  $json = $obj | ConvertTo-Json -Depth 10
  Write-Utf8NoBom -Path $manifestPath -Text $json
  Write-Info "NMH manifest 生成: $manifestPath"

  New-Item -Path $NmhRegistryKey -Force | Out-Null
  Set-ItemProperty -Path $NmhRegistryKey -Name '(default)' -Value $manifestPath
  Write-Info "NMH registry 登録: $NmhRegistryKey"
}

function Unregister-NmhHost {
  $manifestPath = Get-NmhManifestPath
  if ($manifestPath -and (Test-Path -LiteralPath $manifestPath)) {
    Remove-Item -LiteralPath $manifestPath -Force
    Write-Info "NMH manifest 削除: $manifestPath"
  }
  if (Test-Path -LiteralPath $NmhRegistryKey) {
    Remove-Item -LiteralPath $NmhRegistryKey -Recurse -Force
    Write-Info "NMH registry 削除: $NmhRegistryKey"
  } else {
    Write-Info "NMH registry key 不在 (既に削除済): $NmhRegistryKey"
  }
}

function Resolve-Python {
  $cands = @('py -3','python','python3')
  foreach ($c in $cands) {
    try {
      $v = & $c -c "import sys;print(sys.version)" 2>$null
      if ($LASTEXITCODE -eq 0) { return $c }
    } catch { }
  }
  throw "Python 3.9+ not found. Install from https://www.python.org/downloads/"
}

$isExe = $HasExe

if ($Uninstall) {
  Write-Info 'NMH host uninstall mode'
  Unregister-NmhHost
  Write-Host ''
  Write-Info 'NMH host uninstall 完了。'
  return
}

if ($Language) {
  Write-Info "言語設定を保存: $Language"
  Set-LanguagePreference -Lang $Language
  try { $env:LANGUAGE = $Language } catch {}
}

if (-not $isExe -and -not $SkipDeps) {
  $py = Resolve-Python
  Write-Info "Python を使用: $py"

  if (Test-Path (Join-Path $Root 'requirements.txt')) {
    Write-Info '依存関係をインストール: requirements.txt'
    & $py -m pip install -r requirements.txt
  } else {
    Write-Warn 'requirements.txt が見つかりません。スキップします。'
  }

  if ($PDF) {
    Write-Info 'PDF サポート (reportlab) をインストール'
    & $py -m pip install reportlab
  }
} elseif ($SkipDeps) {
  Write-Info '依存関係のインストールはスキップします (-SkipDeps)'
} else {
  Write-Info 'EXE 配布を検出: Python 依存関係のインストールは不要です'
}

# NMH host 登録 (PL-018 CP5)
Write-Info 'NMH (Native Messaging Host) を登録します'
Register-NmhHost

Write-Host ''
Write-Info 'セットアップ完了。Claude に追加されたアイコンから ASA が自動起動します。'
