# installer/install.ps1
# - 신규 PC에서도 0x00000705 방지 (pnputil + PrintUI /ia 조건부)
# - 옵션 적용: ColorMode(컬러/흑백), Duplex(양면해제/양면)
# - 설치 완료 팝업(날짜/시간 포함)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

. "$PSScriptRoot\lib.ps1"

# 팝업용
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

Ensure-Dirs
Write-Log "===== INSTALL START ====="
Write-Log ("PSScriptRoot=" + $PSScriptRoot)

try {
  Assert-Admin

  $workRoot = Split-Path -Parent $PSScriptRoot
  Write-Log ("workRoot=" + $workRoot)

  # config.json 로드 (PS 5.1: -AsHashtable 없음)
  $cfgPath = Join-Path $PSScriptRoot "config.json"
  if (!(Test-Path $cfgPath)) { throw "config.json not found: $cfgPath" }

  $cfg = Get-Content $cfgPath -Raw -Encoding UTF8 | ConvertFrom-Json

  $ip    = [string]$cfg.IP
  $model = [string]$cfg.Model
  $pname = [string]$cfg.PrinterName
  $rel   = [string]$cfg.InfRelPath

  $colorMode = if ($cfg.ColorMode) { [string]$cfg.ColorMode } else { "Color" }     # Color / Mono
  $duplexOpt = if ($cfg.Duplex)    { [string]$cfg.Duplex }    else { "OneSided" }  # OneSided / TwoSidedLongEdge

  if ([string]::IsNullOrWhiteSpace($ip))    { throw "Config IP is empty" }
  if ([string]::IsNullOrWhiteSpace($model)) { throw "Config Model is empty" }
  if ([string]::IsNullOrWhiteSpace($pname)) { throw "Config PrinterName is empty" }
  if ([string]::IsNullOrWhiteSpace($rel))   { throw "Config InfRelPath is empty" }

  $rel = ($rel -replace '/', '\').TrimStart('\')
  Write-Log ("CONFIG: IP=$ip Model=$model PrinterName=$pname InfRelPath=$rel ColorMode=$colorMode Duplex=$duplexOpt")

  # ---- INF 경로 ----
  $inf = Join-Path $workRoot $rel
  if (!(Test-Path $inf)) {
    $inf2 = Join-Path $workRoot ("drivers\" + $rel)
    if (Test-Path $inf2) { $inf = $inf2 }
  }
  if (!(Test-Path $inf)) {
    $infName = Split-Path $rel -Leaf
    $found = Get-ChildItem -Path (Join-Path $workRoot "drivers") -Recurse -Filter $infName -ErrorAction SilentlyContinue | Select-Object -First 1
    if ($found) { $inf = $found.FullName }
  }
  Write-Log ("INF=" + $inf)
  if (!(Test-Path $inf)) { throw "INF not found: $inf" }

  # ---- 포트 선선언 ----
  $port = "IP_$ip"
  Write-Log ("PORT=" + $port)

  # ---- 스풀러 재시작(경고만) ----
  try {
    Stop-Service Spooler -Force -ErrorAction SilentlyContinue
    Start-Service Spooler -ErrorAction SilentlyContinue
  } catch {
    Write-Log ("Spooler warning: " + $_.Exception.Message)
  }

  # ---- Step1: pnputil ----
  Write-Log "Step1: pnputil add-driver/install"
  RunProc "pnputil.exe" @("/add-driver", $inf, "/install") -NoThrow
  Start-Sleep -Seconds 2

  # ---- Step2: 드라이버 이름 등록(신규 PC 핵심) ----
  Write-Log "Step2: Ensure driver registered"
  $drv = Get-PrinterDriver -Name $model -ErrorAction SilentlyContinue
  if (-not $drv) {
    Write-Log "Driver not registered -> PrintUI /ia"
    # 팝업/인수에러 최소화를 위해 cmd 경유 (그래도 뜰 수는 있음)
    cmd.exe /c "rundll32 printui.dll,PrintUIEntry /ia /m `"$model`" /f `"$inf`"" | Out-Null
    Start-Sleep -Seconds 3
  } else {
    Write-Log "Driver already registered"
  }

  # 드라이버 최종 확인
  $drv2 = Get-PrinterDriver -Name $model -ErrorAction SilentlyContinue
  if (-not $drv2) { throw "Driver still not registered: $model" }

  # ---- Step3: 포트 생성 ----
  Write-Log "Step3: Ensure port"
  if (-not (Get-PrinterPort -Name $port -ErrorAction SilentlyContinue)) {
    Add-PrinterPort -Name $port -PrinterHostAddress $ip
    Write-Log "Port created"
  } else {
    Write-Log "Port exists"
  }

  # ---- Step4: 프린터 생성 ----
  Write-Log "Step4: Add/Update printer"
  $printer = Get-Printer -Name $pname -ErrorAction SilentlyContinue

  if (-not $printer) {
    try {
      Add-Printer -Name $pname -DriverName $model -PortName $port
      Write-Log "Printer created (Add-Printer)"
    } catch {
      Write-Log ("Add-Printer failed: " + $_.Exception.Message)
      Write-Log "Fallback: PrintUI /if"
      cmd.exe /c "rundll32 printui.dll,PrintUIEntry /if /b `"$pname`" /r `"$port`" /m `"$model`" /f `"$inf`"" | Out-Null
    }
  } else {
    Write-Log "Printer already exists"
    try {
      if ($printer.PortName -ne $port) {
        Set-Printer -Name $pname -PortName $port
        Write-Log "Printer port updated"
      }
    } catch {
      Write-Log ("Set-Printer warning: " + $_.Exception.Message)
    }
  }

  # ---- Step4.5: 옵션 적용 (컬러/흑백 + 양면) ----
  Write-Log "Step4.5: Apply default print options"
  try {
    Import-Module PrintManagement -ErrorAction SilentlyContinue

    $setColor = $true
    if ($colorMode -match '^(?i)mono|bw|blackwhite|black_white|흑백$') { $setColor = $false }

    $duplexMode = "OneSided"
    if ($duplexOpt -match '^(?i)twosidedlongedge|long$') { $duplexMode = "TwoSidedLongEdge" }
    elseif ($duplexOpt -match '^(?i)twosidedshortedge|short$') { $duplexMode = "TwoSidedShortEdge" }
    elseif ($duplexOpt -match '^(?i)onesided|off|disable|해제|단면$') { $duplexMode = "OneSided" }

    Set-PrintConfiguration -PrinterName $pname -Color $setColor -DuplexingMode $duplexMode -ErrorAction Stop

    $pc = Get-PrintConfiguration -PrinterName $pname -ErrorAction SilentlyContinue
    if ($pc) {
      Write-Log ("Applied PrintConfiguration: Color=" + $pc.Color + ", DuplexingMode=" + $pc.DuplexingMode)
    } else {
      Write-Log "WARN: Get-PrintConfiguration returned null"
    }
  } catch {
    # 일부 드라이버는 cmdlet 설정을 무시할 수 있어 경고만
    Write-Log ("WARN: Apply options failed/ignored: " + $_.Exception.Message)
  }

  # ---- Step5: 최종 검증 ----
  Write-Log "Step5: Verify"
  $finalPrinter = Get-Printer -Name $pname -ErrorAction SilentlyContinue
  if (-not $finalPrinter) { throw "Printer not found after install: $pname" }

  Write-Log ("Verified printer: " + $finalPrinter.Name + " / Driver=" + $finalPrinter.DriverName + " / Port=" + $finalPrinter.PortName)

  # ---- 고객용 설치 완료 팝업 ----
  $installedAt = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
  [System.Windows.Forms.MessageBox]::Show(
    "프린터 설치가 완료되었습니다.`r`n`r`n프린터 이름: $pname`r`n모델: $model`r`n컬러/흑백: $colorMode`r`n양면: $duplexOpt`r`n설치 시각: $installedAt",
    "설치 완료",
    [System.Windows.Forms.MessageBoxButtons]::OK,
    [System.Windows.Forms.MessageBoxIcon]::Information
  ) | Out-Null

  Write-Log "===== INSTALL DONE (OK) ====="
  exit 0

} catch {
  # 실패 팝업(고객용)
  $msg = $_.Exception.Message
  try {
    [System.Windows.Forms.MessageBox]::Show(
      "프린터 설치에 실패했습니다.`r`n`r`n오류: $msg",
      "설치 실패",
      [System.Windows.Forms.MessageBoxButtons]::OK,
      [System.Windows.Forms.MessageBoxIcon]::Error
    ) | Out-Null
  } catch {}

  Write-Log "===== INSTALL FAILED ====="
  Write-Log ($_.Exception.ToString())
  throw
}
