param(
    [ValidateSet('menu', 'install', 'uninstall', 'enable', 'disable', 'start', 'stop', 'restart', 'status', 'logs', 'config', 'help', 'message')]
    [string]$Action = 'menu',
    [ValidateSet('auto', 'zh', 'en')]
    [string]$Language = 'auto',
    [string]$Executable = '',
    [string]$ConfigPath = '',
    [string]$ListenAddress = '',
    [string]$DatabasePath = '',
    [switch]$CookieSecure,
    [ValidateSet('install', 'uninstall', 'start', 'stop', 'open-ui')]
    [string]$MessageAction = 'start',
    [int]$MessageExitCode = 0,
    [string]$MessageURL = ''
)

$ErrorActionPreference = 'Stop'
$OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new()
$Root = $PSScriptRoot
# Release scripts live beside nowdns.exe; source scripts live under scripts/.
if ((Split-Path -Leaf $Root) -eq 'scripts') {
    $sourceRoot = Split-Path -Parent $Root
    if (Test-Path -LiteralPath (Join-Path $sourceRoot 'bin') -PathType Container) {
        $Root = $sourceRoot
    }
}

function Resolve-Language {
    if ($Language -ne 'auto') { return $Language }
    $culture = [Globalization.CultureInfo]::CurrentUICulture.TwoLetterISOLanguageName
    if ($culture -eq 'zh') { return 'zh' }
    return 'en'
}

$script:CurrentLanguage = Resolve-Language

function T([string]$Zh, [string]$En) {
    if ($script:CurrentLanguage -eq 'zh') { return $Zh }
    return $En
}

function Write-Message([string]$Zh, [string]$En, [ConsoleColor]$Color = [ConsoleColor]::Gray) {
    Write-Host (T $Zh $En) -ForegroundColor $Color
}

function Resolve-Executable {
    if ($Executable) {
        $candidate = if ([IO.Path]::IsPathRooted($Executable)) { $Executable } else { Join-Path $Root $Executable }
        if (Test-Path -LiteralPath $candidate -PathType Leaf) { return (Resolve-Path -LiteralPath $candidate).Path }
        throw (T "找不到 NowDNS 可执行文件: $candidate" "NowDNS executable was not found: $candidate")
    }
    $architecture = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE }
    $arch = switch ($architecture.ToUpperInvariant()) {
        'AMD64' { 'amd64' }
        'ARM64' { 'arm64' }
        default { throw (T "不支持的 Windows 架构: $architecture" "Unsupported Windows architecture: $architecture") }
    }
    $packagedCandidate = Join-Path $Root 'nowdns.exe'
    if (Test-Path -LiteralPath $packagedCandidate -PathType Leaf) {
        return (Resolve-Path -LiteralPath $packagedCandidate).Path
    }
    $candidate = Get-ChildItem -LiteralPath (Join-Path $Root 'bin') -File -Filter "nowdns-*-windows-$arch.exe" -ErrorAction SilentlyContinue |
        Sort-Object LastWriteTime -Descending |
        Select-Object -First 1
    if (-not $candidate) {
        throw (T "未找到 nowdns.exe 或 bin/nowdns-*-windows-$arch.exe。请先下载或构建 Windows 版本。" "No nowdns.exe or bin/nowdns-*-windows-$arch.exe was found. Download or build the Windows release first.")
    }
    return $candidate.FullName
}

function Test-Administrator {
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = [Security.Principal.WindowsPrincipal]::new($identity)
    return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

function Require-Administrator {
    if (-not (Test-Administrator)) {
        throw (T '请以管理员身份打开 PowerShell 后重新运行此操作。' 'Open PowerShell as Administrator, then run this operation again.')
    }
}

function Invoke-NowDNSService([string]$Verb) {
    $binary = Resolve-Executable
    $arguments = @('service', $Verb)
    if ($Verb -eq 'install') {
        if ($ConfigPath) { $arguments += @('--config', $ConfigPath) }
        if ($ListenAddress) { $arguments += @('--listen', $ListenAddress) }
        if ($DatabasePath) { $arguments += @('--database', $DatabasePath) }
        if ($CookieSecure) { $arguments += '--cookie-secure=true' }
    }
    Push-Location $Root
    try {
        & $binary @arguments
        if ($LASTEXITCODE -ne 0) { throw (T "NowDNS 服务命令失败，退出码: $LASTEXITCODE" "NowDNS service command failed with exit code: $LASTEXITCODE") }
    } finally {
        Pop-Location
    }
}

# Derives the local management URL the same way the server banner does:
# wildcard hosts map to 127.0.0.1 so a bound-anywhere listener stays clickable.
function Resolve-ManagementUrl {
    $listen = ''
    if ($ListenAddress) {
        $listen = $ListenAddress
    } else {
        $config = if ($ConfigPath) {
            if ([IO.Path]::IsPathRooted($ConfigPath)) { $ConfigPath } else { Join-Path $Root $ConfigPath }
        } else {
            Join-Path $Root 'config.yaml'
        }
        if (Test-Path -LiteralPath $config -PathType Leaf) {
            foreach ($line in Get-Content -LiteralPath $config) {
                if ($line -match '^\s*listen:\s*(.+?)\s*(#.*)?$') {
                    $listen = $Matches[1].Trim('"', "'")
                    break
                }
            }
        }
    }
    if (-not $listen) { return 'http://127.0.0.1:8080' }

    $urlHost = '127.0.0.1'
    $urlPort = '8080'
    if ($listen.StartsWith('[')) {
        if ($listen -match '^\[(.+)\]:(\d+)$') { $urlHost = $Matches[1]; $urlPort = $Matches[2] }
    } elseif ($listen -match '^([^:\[]*):(\d+)$') {
        $urlHost = $Matches[1]; $urlPort = $Matches[2]
    } elseif ($listen -match '^:(\d+)$') {
        $urlPort = $Matches[1]
    }
    switch ($urlHost.ToLowerInvariant()) {
        '' { $urlHost = '127.0.0.1' }
        '0.0.0.0' { $urlHost = '127.0.0.1' }
        '::' { $urlHost = '127.0.0.1' }
        '*' { $urlHost = '127.0.0.1' }
        'any' { $urlHost = '127.0.0.1' }
    }
    $displayHost = if ($urlHost.Contains(':')) { "[$urlHost]" } else { $urlHost }
    return "http://${displayHost}:${urlPort}"
}

function Test-TcpReady([string]$ProbeHost, [string]$ProbePort) {
    $deadline = [DateTime]::UtcNow.AddSeconds(20)
    while ([DateTime]::UtcNow -lt $deadline) {
        $client = [Net.Sockets.TcpClient]::new()
        try {
            if ($client.ConnectAsync($ProbeHost, [int]$ProbePort).Wait(300)) { return $true }
        } catch {
        } finally {
            $client.Dispose()
        }
        Start-Sleep -Milliseconds 400
    }
    return $false
}

# Best effort: never turn a failed browser launch into a failed install.
function Open-ManagementUI {
    try {
        $url = Resolve-ManagementUrl
        if ($url -match '^http://\[(.+)\]:(\d+)$') {
            $probeHost, $probePort, $displayHost = $Matches[1], $Matches[2], "[$($Matches[1])]"
        } elseif ($url -match '^http://([^:\[]+):(\d+)$') {
            $probeHost, $probePort, $displayHost = $Matches[1], $Matches[2], $Matches[1]
        } else {
            Write-Message "无法解析管理界面地址，请手动访问。" "Could not resolve the management URL; please open it manually." Yellow
            return
        }
        if (-not (Test-TcpReady $probeHost $probePort)) {
            Write-Message "服务端口尚未就绪，稍后请手动访问管理界面: $url" "The service port is not ready yet; open the management UI later: $url" Yellow
            return
        }
        Start-Process $url | Out-Null
        Write-Message "已在默认浏览器打开管理界面: $url" "Opened the management UI in your default browser: $url" Green
    } catch {
        Write-Message "自动打开浏览器失败，请手动访问管理界面。" "Failed to launch the browser automatically; please open the management UI manually." Yellow
    }
}

function Show-Logs {
    $logPath = Join-Path $Root 'data\logs\nowdns.log'
    $accessPath = Join-Path $Root 'data\logs\nowdns-access.log'
    Write-Message "应用日志: $logPath" "Application log: $logPath" Cyan
    if (Test-Path -LiteralPath $logPath) { Get-Content -LiteralPath $logPath -Tail 50 } else { Write-Message '应用日志尚未创建。' 'Application log has not been created yet.' Yellow }
    Write-Message "`nHTTP 访问日志: $accessPath" "`nHTTP access log: $accessPath" Cyan
    if (Test-Path -LiteralPath $accessPath) { Get-Content -LiteralPath $accessPath -Tail 50 } else { Write-Message 'HTTP 访问日志尚未创建。' 'HTTP access log has not been created yet.' Yellow }
}

function Show-Configuration {
    $config = Join-Path $Root 'config.yaml'
    if (Test-Path -LiteralPath $config) {
        Write-Message "当前配置: $config" "Current configuration: $config" Cyan
        Get-Content -LiteralPath $config
    } else {
        Write-Message "尚未生成 config.yaml。执行安装会生成默认配置。" "config.yaml has not been generated. Installing the service creates the default configuration." Yellow
    }
}

function Show-Usage {
    Write-Message '用法: .\service.ps1 [-Action action] [-Language auto|zh|en]' 'Usage: .\service.ps1 [-Action action] [-Language auto|zh|en]'
    Write-Message 'Action: menu、install、uninstall、enable、disable、start、stop、restart、status、logs、config、help' 'Action: menu, install, uninstall, enable, disable, start, stop, restart, status, logs, config, help'
    Write-Message '安装参数: -Executable、-ConfigPath、-ListenAddress、-DatabasePath、-CookieSecure' 'Install options: -Executable, -ConfigPath, -ListenAddress, -DatabasePath, -CookieSecure'
    Write-Message '安装完成后会在服务端口就绪时自动打开管理界面。' 'After installing, the management UI opens automatically once the service port is ready.'
}

function Show-LauncherMessage {
    if ($MessageExitCode -eq 0) {
        switch ($MessageAction) {
            'install' { Write-Host 'NowDNS 服务已安装并启动。按任意键关闭窗口...' -ForegroundColor Green }
            'uninstall' { Write-Host 'NowDNS 服务已卸载。按任意键关闭窗口...' -ForegroundColor Green }
            'start' { Write-Host 'NowDNS 服务已启动。按任意键关闭窗口...' -ForegroundColor Green }
            'stop' { Write-Host 'NowDNS 服务已停止。按任意键关闭窗口...' -ForegroundColor Green }
            'open-ui' { Write-Host "已请求默认浏览器打开 $MessageURL。按任意键关闭窗口..." -ForegroundColor Green }
        }
        return
    }
    switch ($MessageAction) {
        'install' { Write-Host "NowDNS 服务安装失败，退出码：$MessageExitCode。按任意键关闭窗口..." -ForegroundColor Red }
        'uninstall' { Write-Host "NowDNS 服务卸载失败，退出码：$MessageExitCode。按任意键关闭窗口..." -ForegroundColor Red }
        'start' { Write-Host "NowDNS 服务启动失败，退出码：$MessageExitCode。按任意键关闭窗口..." -ForegroundColor Red }
        'stop' { Write-Host "NowDNS 服务停止失败，退出码：$MessageExitCode。按任意键关闭窗口..." -ForegroundColor Red }
        'open-ui' { Write-Host "无法打开管理界面，退出码：$MessageExitCode。按任意键关闭窗口..." -ForegroundColor Red }
    }
}

function Show-Menu {
    Clear-Host
    Write-Message 'NowDNS Windows 服务管理' 'NowDNS Windows Service Manager' Cyan
    Write-Message "工作目录: $Root" "Working directory: $Root"
    Write-Host ''
	Write-Message '1. 安装、启动并设置开机自启' '1. Install, start, and enable automatic startup'
    Write-Message '2. 启动服务' '2. Start service'
    Write-Message '3. 停止服务' '3. Stop service'
    Write-Message '4. 重启服务' '4. Restart service'
    Write-Message '5. 查看服务状态' '5. Show service status'
    Write-Message '6. 查看最近日志' '6. Show recent logs'
    Write-Message '7. 查看配置' '7. Show configuration'
    Write-Message '8. 启用开机自启' '8. Enable automatic startup'
    Write-Message '9. 停止并禁用开机自启' '9. Stop and disable automatic startup'
    Write-Message '10. 卸载服务' '10. Uninstall service'
    Write-Message '11. 切换中文/English' '11. Switch Chinese/English'
    Write-Message '0. 退出' '0. Exit'
    return (Read-Host (T '请选择' 'Choose an action'))
}

function Invoke-Action([string]$SelectedAction) {
    switch ($SelectedAction) {
        'install' { Require-Administrator; Invoke-NowDNSService 'install'; Open-ManagementUI }
        'uninstall' { Require-Administrator; Invoke-NowDNSService 'uninstall' }
        'enable' { Require-Administrator; Invoke-NowDNSService 'enable' }
        'disable' { Require-Administrator; Invoke-NowDNSService 'disable' }
        'start' { Require-Administrator; Invoke-NowDNSService 'start' }
        'stop' { Require-Administrator; Invoke-NowDNSService 'stop' }
        'restart' { Require-Administrator; Invoke-NowDNSService 'restart' }
        'status' { Invoke-NowDNSService 'status' }
        'logs' { Show-Logs }
        'config' { Show-Configuration }
        'help' { Show-Usage }
        'message' { Show-LauncherMessage }
    }
}

if ($Action -ne 'menu') {
    Invoke-Action $Action
    exit 0
}

while ($true) {
    $selection = Show-Menu
    try {
        switch ($selection) {
            '1' { Invoke-Action 'install' }
            '2' { Invoke-Action 'start' }
            '3' { Invoke-Action 'stop' }
            '4' { Invoke-Action 'restart' }
            '5' { Invoke-Action 'status' }
            '6' { Invoke-Action 'logs' }
            '7' { Invoke-Action 'config' }
            '8' { Invoke-Action 'enable' }
            '9' { Invoke-Action 'disable' }
            '10' { Invoke-Action 'uninstall' }
            '11' { $script:CurrentLanguage = if ($script:CurrentLanguage -eq 'zh') { 'en' } else { 'zh' }; continue }
            '0' { return }
            default { Write-Message '无效选择。' 'Invalid selection.' Yellow }
        }
    } catch {
        Write-Host $_.Exception.Message -ForegroundColor Red
    }
    if ($selection -ne '11') { [void](Read-Host (T '按 Enter 返回菜单' 'Press Enter to return to the menu')) }
}
