@echo off
setlocal

set "AUTONAP_ELEVATED_FLAG=%~1"
if "%AUTONAP_ELEVATED_FLAG%"=="--elevated" shift

set "AUTONAP_BASE=%~dp0."
set "AUTONAP_SELF=%~f0"
set "AUTONAP_PS1=%TEMP%\AutoNapLic_%RANDOM%%RANDOM%.ps1"
set "AUTONAP_LOG=%AUTONAP_BASE%\AutoNapLic.log.txt"

>>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD start.

powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$p=New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()); if($p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){exit 0}else{exit 1}" >nul 2>&1
if not "%ERRORLEVEL%"=="0" (
  >>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD not admin.
  if "%AUTONAP_ELEVATED_FLAG%"=="--elevated" (
    >>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD already elevated flag but still not admin.
    echo Mo Auto That bai lien he Support de ho tro.
    pause
    exit /b 1
  )
  >>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD request admin relaunch.
  powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "try { $psi=New-Object System.Diagnostics.ProcessStartInfo; $psi.FileName=$env:ComSpec; $psi.Arguments=('/c ""' + $env:AUTONAP_SELF + '"" --elevated'); $psi.WorkingDirectory=$env:AUTONAP_BASE; $psi.Verb='runas'; $psi.UseShellExecute=$true; [System.Diagnostics.Process]::Start($psi) | Out-Null; exit 0 } catch { exit 1 }"
  if errorlevel 1 (
    >>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD admin relaunch failed or was cancelled.
    echo Mo Auto That bai lien he Support de ho tro.
    pause
    exit /b 1
  )
  >>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD admin relaunch requested, current process exits.
  exit /b 0
)

>>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD running as admin.
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$src=$env:AUTONAP_SELF; $dst=$env:AUTONAP_PS1; $lines=[IO.File]::ReadAllLines($src); $start=-1; for($i=0;$i -lt $lines.Length;$i++){ if($lines[$i] -eq '### POWERSHELL ###'){ $start=$i+1; break } }; if($start -lt 0){ exit 2 }; $body=$lines[$start..($lines.Length-1)]; [IO.File]::WriteAllLines($dst,$body,[Text.Encoding]::UTF8)"
if errorlevel 1 (
  >>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD prepare temp powershell failed.
  echo Khong the chuan bi script nap lic.
  pause
  exit /b 1
)

>>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD prepared temp powershell: %AUTONAP_PS1%
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%AUTONAP_PS1%" -BaseDir "%AUTONAP_BASE%" %*
set "AUTONAP_EXIT=%ERRORLEVEL%"
>>"%AUTONAP_LOG%" echo [%DATE% %TIME%] CMD powershell exit code: %AUTONAP_EXIT%

if not "%AUTONAP_EXIT%"=="0" (
  echo.
  echo Nap lic chua thanh cong. Hay xem file AutoNapLic.log.txt.
  pause
)

exit /b %AUTONAP_EXIT%

### POWERSHELL ###
param(
    [string]$BaseDir = "",
    [string]$ConfigFile = ""
)

$ErrorActionPreference = "Stop"

if ([string]::IsNullOrEmpty($BaseDir)) {
    $BaseDir = Split-Path -Parent $MyInvocation.MyCommand.Path
}
$BaseDir = $BaseDir.Trim().Trim('"')
$BaseDir = [IO.Path]::GetFullPath($BaseDir)

if ([string]::IsNullOrEmpty($ConfigFile)) {
    $ConfigFile = Join-Path $BaseDir "AutoNapLic.txt"
}
elseif (-not [IO.Path]::IsPathRooted($ConfigFile)) {
    $ConfigFile = Join-Path $BaseDir $ConfigFile
}

$LogFile = Join-Path $BaseDir "AutoNapLic.log.txt"

function Write-Log {
    param([string]$Message)
    try {
        $line = "{0:yyyy-MM-dd HH:mm:ss} {1}" -f (Get-Date), $Message
        Add-Content -LiteralPath $LogFile -Value $line -Encoding UTF8
    }
    catch {
    }
}

function Resolve-LocalPath {
    param([string]$PathValue, [string]$Root)
    if ([string]::IsNullOrEmpty($PathValue)) {
        return ""
    }
    $expanded = [Environment]::ExpandEnvironmentVariables($PathValue.Trim())
    if ([IO.Path]::IsPathRooted($expanded)) {
        return $expanded
    }
    return Join-Path $Root $expanded
}

function Read-Config {
    param([string]$Path)

    $config = @{}
    $config["ExePath"] = ""
    $config["License"] = ""
    $config["LicenseFile"] = ""
    $config["AutoStart"] = "true"
    $config["ApplyAfterFill"] = "true"
    $config["WaitSeconds"] = "5"
    $config["MaxAttempts"] = "5"
    $config["AttemptDelaySeconds"] = "3"
    $config["RequireApplySuccess"] = "false"
    $config["SkipStartupPopups"] = "true"
    $config["ProcessNames"] = "vauth.auto,KYKeoxe,KimYen_Ver12,KimYen"

    if (-not (Test-Path -LiteralPath $Path)) {
        throw "Khong tim thay file cau hinh: $Path"
    }

    $configDir = Split-Path -Parent $Path
    $lines = [IO.File]::ReadAllLines($Path)
    foreach ($line in $lines) {
        $trimmed = $line.Trim()
        if ([string]::IsNullOrEmpty($trimmed) -or $trimmed.StartsWith("#")) {
            continue
        }

        $pos = $trimmed.IndexOf("=")
        if ($pos -lt 0) {
            continue
        }

        $name = $trimmed.Substring(0, $pos).Trim()
        $value = $trimmed.Substring($pos + 1).Trim()
        $config[$name] = $value
    }

    if (-not [string]::IsNullOrEmpty($config["ExePath"])) {
        $config["ExePath"] = Resolve-LocalPath $config["ExePath"] $configDir
    }
    if (-not [string]::IsNullOrEmpty($config["LicenseFile"])) {
        $config["LicenseFile"] = Resolve-LocalPath $config["LicenseFile"] $configDir
    }

    return $config
}

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

function Clean-LicenseText {
    param([string]$Text)
    if ($null -eq $Text) {
        return ""
    }
    return $Text.Trim().Replace(":", "").Replace("`t", "").Replace(" ", "").Replace("`r", "").Replace("`n", "")
}

function Get-License {
    param($Config)

    if (-not [string]::IsNullOrEmpty($Config["LicenseFile"])) {
        if (-not (Test-Path -LiteralPath $Config["LicenseFile"])) {
            throw "Khong tim thay LicenseFile: $($Config["LicenseFile"])"
        }
        return Clean-LicenseText ([IO.File]::ReadAllText($Config["LicenseFile"]))
    }

    return Clean-LicenseText $Config["License"]
}

function Find-ExePath {
    param($Config, [string]$Root)

    if (-not [string]::IsNullOrEmpty($Config["ExePath"])) {
        if (-not (Test-Path -LiteralPath $Config["ExePath"])) {
            throw "Khong tim thay ExePath: $($Config["ExePath"])"
        }
        return (Get-Item -LiteralPath $Config["ExePath"]).FullName
    }

    $preferred = @("KimYen_Ver12.exe", "KYKeoxe.exe")
    foreach ($name in $preferred) {
        $path = Join-Path $Root $name
        if (Test-Path -LiteralPath $path) {
            return (Get-Item -LiteralPath $path).FullName
        }
    }

    $exe = Get-ChildItem -LiteralPath $Root -Filter "*.exe" | Where-Object {
        $_.Name -ne "AutoNapLic.exe" -and $_.Name -ne "AutoNapLic.cmd"
    } | Select-Object -First 1
    if ($null -ne $exe) {
        return $exe.FullName
    }

    throw "Khong tim thay file auto .exe trong thu muc: $Root"
}

function Write-RegistryValue {
    param([string]$LicenseText, [bool]$SkipStartupPopups)

    $keys = @(
        "HKLM\SOFTWARE\KYKeoxe",
        "HKLM\SOFTWARE\WOW6432Node\KYKeoxe",
        "HKLM\SOFTWARE\AutoVLTK",
        "HKLM\SOFTWARE\WOW6432Node\AutoVLTK"
    )

    foreach ($key in $keys) {
        try {
            & reg.exe add $key /v textIDSudung /t REG_SZ /d $LicenseText /f | Out-Null
            Write-Log "Registry OK: $key"
            if ($SkipStartupPopups) {
                & reg.exe add $key /v KhongHienThiVideoHelp /t REG_SZ /d 1 /f | Out-Null
                Write-Log "Registry startup popup flags OK: $key"
            }
        }
        catch {
            Write-Log "Registry failed: $key - $($_.Exception.Message)"
        }
    }
}

function Write-LicenseFiles {
    param([string]$ExePath, [string]$LicenseText)

    $exeDir = [IO.Path]::GetDirectoryName($ExePath)
    $configDir = Join-Path $exeDir "Config"
    if (-not (Test-Path -LiteralPath $configDir)) {
        [IO.Directory]::CreateDirectory($configDir) | Out-Null
    }

    $target = Join-Path $configDir "KYKeoxe.txt"
    [IO.File]::WriteAllText($target, $LicenseText, [Text.Encoding]::ASCII)
    Write-Log "Wrote file: $target"

    try {
        $winTarget = Join-Path $env:windir "KYKeoxe.txt"
        [IO.File]::WriteAllText($winTarget, $LicenseText, [Text.Encoding]::ASCII)
        Write-Log "Wrote file: $winTarget"
    }
    catch {
        Write-Log "Skip windir KYKeoxe.txt: $($_.Exception.Message)"
    }
}

function Start-LiteralProcess {
    param([string]$FilePath, [string]$WorkingDirectory)

    $psi = New-Object System.Diagnostics.ProcessStartInfo
    $psi.FileName = $FilePath
    if (-not [string]::IsNullOrEmpty($WorkingDirectory)) {
        $psi.WorkingDirectory = $WorkingDirectory
    }
    $psi.UseShellExecute = $false
    try {
        $process = [System.Diagnostics.Process]::Start($psi)
        if ($null -eq $process) {
            throw "Process.Start returned null"
        }
        Write-Log ("Started process by CreateProcess. pid={0}" -f $process.Id)
        return
    }
    catch {
        Write-Log ("CreateProcess start failed: {0}" -f $_.Exception.Message)
    }

    $shellPsi = New-Object System.Diagnostics.ProcessStartInfo
    $shellPsi.FileName = $FilePath
    if (-not [string]::IsNullOrEmpty($WorkingDirectory)) {
        $shellPsi.WorkingDirectory = $WorkingDirectory
    }
    $shellPsi.UseShellExecute = $true
    try {
        $process = [System.Diagnostics.Process]::Start($shellPsi)
        if ($null -eq $process) {
            throw "Process.Start returned null"
        }
        Write-Log ("Started process by ShellExecute. pid={0}" -f $process.Id)
        return
    }
    catch {
        throw "Khong the mo auto: $FilePath. Loi: $($_.Exception.Message)"
    }
}

function Show-FailMessage {
    param([string]$Message)
    try {
        Add-Type -AssemblyName System.Windows.Forms
        [System.Windows.Forms.MessageBox]::Show($Message, "AutoNapLic", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null
    }
    catch {
        Write-Host $Message
    }
}

function Write-WindowSnapshot {
    try {
        Write-Log "Visible window snapshot begin"
        $items = Get-Process | Where-Object { $_.MainWindowHandle -ne 0 } | Select-Object -First 40
        foreach ($item in $items) {
            $title = ""
            try { $title = $item.MainWindowTitle } catch { }
            Write-Log ("Window: process={0} pid={1} title={2}" -f $item.ProcessName, $item.Id, $title)
        }
        Write-Log "Visible window snapshot end"
    }
    catch {
        Write-Log ("Window snapshot failed: {0}" -f $_.Exception.Message)
    }
}

function Test-StartupPopupTitle {
    param([string]$Title)
    if ([string]::IsNullOrEmpty($Title)) {
        return $false
    }

    $upper = $Title.ToUpperInvariant()
    return (
        $upper -eq "PHIM HUONG DAN" -or
        $upper -eq "PHIEN BAN MOI" -or
        $upper -eq "HUONG DAN" -or
        $upper -eq "LUU Y" -or
        $upper -eq "CAP NHAT AUTO"
    )
}

function Set-LicenseInAutoWindow {
    param([string]$LicenseText, [string[]]$Names)

    Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes
    if (-not ("KimYenWin32" -as [type])) {
        Add-Type @'
using System;
using System.Runtime.InteropServices;
public static class KimYenWin32 {
    [DllImport("user32.dll", CharSet=CharSet.Unicode)]
    public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int X, int Y);

    [DllImport("user32.dll")]
    public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);
}
'@
    }

    $wmSetText = 0x000C
    $wmClose = 0x0010
    $bmClick = 0x00F5
    $mouseLeftDown = 0x0002
    $mouseLeftUp = 0x0004
    $filled = 0
    $lowerNames = @()
    foreach ($name in $Names) {
        if (-not [string]::IsNullOrEmpty($name)) {
            $lowerNames += $name.Trim().ToLowerInvariant()
        }
    }

    $processes = Get-Process | Where-Object {
        if ($_.MainWindowHandle -eq 0) { return $false }
        $processName = $_.ProcessName.ToLowerInvariant()
        $title = ""
        try { $title = $_.MainWindowTitle } catch { }
        foreach ($name in $lowerNames) {
            if ($processName -eq $name -or $processName -like ("*" + $name + "*")) {
                return $true
            }
        }
        return ($title -like "*KY-*" -or $title -like "*KimYen*" -or $title -like "*Kim Y*")
    }

    foreach ($process in $processes) {
        try {
            $root = [System.Windows.Automation.AutomationElement]::FromHandle($process.MainWindowHandle)
            if ($null -eq $root) {
                continue
            }

            Write-Log ("Scan window: {0} pid={1} title={2}" -f $process.ProcessName, $process.Id, $root.Current.Name)
            $all = $root.FindAll([System.Windows.Automation.TreeScope]::Descendants, [System.Windows.Automation.Condition]::TrueCondition)
            if (Test-StartupPopupTitle $root.Current.Name) {
                $clickedHide = $false
                for ($i = 0; $i -lt $all.Count; $i++) {
                    $element = $all.Item($i)
                    $isCheckBox = $false
                    try { $isCheckBox = ($element.Current.ControlType.ProgrammaticName -eq "ControlType.CheckBox") } catch { }
                    if ($isCheckBox -and $element.Current.NativeWindowHandle -ne 0) {
                        $shouldClick = $true
                        try {
                            $togglePattern = $null
                            if ($element.TryGetCurrentPattern([System.Windows.Automation.TogglePattern]::Pattern, [ref]$togglePattern)) {
                                $shouldClick = ($togglePattern.Current.ToggleState -ne [System.Windows.Automation.ToggleState]::On)
                            }
                        }
                        catch {
                            $shouldClick = $true
                        }
                        if ($shouldClick) {
                            [KimYenWin32]::SendMessage([IntPtr]$element.Current.NativeWindowHandle, $bmClick, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null
                            $clickedHide = $true
                            Start-Sleep -Milliseconds 200
                        }
                        break
                    }
                }
                [KimYenWin32]::SendMessage([IntPtr]$process.MainWindowHandle, $wmClose, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null
                Write-Log ("Dismissed startup popup: title={0} clickedHide={1}" -f $root.Current.Name, $clickedHide)
                Start-Sleep -Milliseconds 500
                continue
            }

            $target = $null
            $idLabel = $null

            for ($i = 0; $i -lt $all.Count; $i++) {
                $element = $all.Item($i)
                if ($element.Current.Name -eq "ID" -and $element.Current.ClassName -like "WindowsForms10.STATIC*") {
                    $idLabel = $element
                }
                if ($element.Current.ClassName -like "WindowsForms10.EDIT*" -and ($element.Current.Name -eq "nhap_id_vao_day" -or $element.Current.Name -like "*nhap_id*")) {
                    $target = $element
                    break
                }
            }

            if ($null -eq $target -and $null -ne $idLabel) {
                $labelRect = $idLabel.Current.BoundingRectangle
                $bestDistance = [double]::MaxValue
                for ($i = 0; $i -lt $all.Count; $i++) {
                    $element = $all.Item($i)
                    if ($element.Current.ClassName -notlike "WindowsForms10.EDIT*") {
                        continue
                    }
                    $rect = $element.Current.BoundingRectangle
                    $verticalDistance = [Math]::Abs($rect.Y - $labelRect.Y)
                    $horizontalDistance = $rect.X - $labelRect.X
                    if ($verticalDistance -le 20 -and $horizontalDistance -gt 0 -and $horizontalDistance -lt $bestDistance) {
                        $bestDistance = $horizontalDistance
                        $target = $element
                    }
                }
            }

            if ($null -eq $target) {
                Write-Log "No ID edit box found."
                continue
            }

            $apply = $null
            $targetRect = $target.Current.BoundingRectangle
            $bestApplyDistance = [double]::MaxValue

            for ($i = 0; $i -lt $all.Count; $i++) {
                $element = $all.Item($i)
                if ($element.Current.ClassName -notlike "WindowsForms10.BUTTON*") {
                    continue
                }

                $rect = $element.Current.BoundingRectangle
                $sameRow = [Math]::Abs($rect.Y - $targetRect.Y) -le 12
                $rightOfBox = $rect.X -ge ($targetRect.X + $targetRect.Width)
                $wideEnough = $rect.Width -ge 45
                if (-not ($sameRow -and $rightOfBox -and $wideEnough)) {
                    continue
                }

                $distance = [Math]::Abs($rect.Y - $targetRect.Y) + [Math]::Max(0, $rect.X - $targetRect.X)
                if ($distance -lt $bestApplyDistance) {
                    $bestApplyDistance = $distance
                    $apply = $element
                }
            }

            [KimYenWin32]::SetForegroundWindow([IntPtr]$process.MainWindowHandle) | Out-Null
            [KimYenWin32]::SendMessage([IntPtr]$target.Current.NativeWindowHandle, $wmSetText, [IntPtr]::Zero, $LicenseText) | Out-Null
            Start-Sleep -Milliseconds 250

            if ($null -ne $apply) {
                [KimYenWin32]::SendMessage([IntPtr]$apply.Current.NativeWindowHandle, $bmClick, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null
                Start-Sleep -Milliseconds 200

                $applyRect = $apply.Current.BoundingRectangle
                $clickX = [int]($applyRect.X + ($applyRect.Width / 2))
                $clickY = [int]($applyRect.Y + ($applyRect.Height / 2))
                [KimYenWin32]::SetCursorPos($clickX, $clickY) | Out-Null
                Start-Sleep -Milliseconds 100
                [KimYenWin32]::mouse_event($mouseLeftDown, 0, 0, 0, [IntPtr]::Zero)
                Start-Sleep -Milliseconds 80
                [KimYenWin32]::mouse_event($mouseLeftUp, 0, 0, 0, [IntPtr]::Zero)

                Write-Log ("Filled and clicked Apply. editHwnd={0} applyHwnd={1} click={2},{3}" -f $target.Current.NativeWindowHandle, $apply.Current.NativeWindowHandle, $clickX, $clickY)
            }
            else {
                Write-Log ("Filled but Apply button was not found. editHwnd={0}" -f $target.Current.NativeWindowHandle)
            }

            $filled++
        }
        catch {
            Write-Log ("UI fill failed for pid={0}: {1}" -f $process.Id, $_.Exception.Message)
        }
    }

    return $filled
}

try {
    Write-Log "===== Start ====="
    $config = Read-Config $ConfigFile
    $license = Get-License $config
    if ([string]::IsNullOrEmpty($license)) {
        throw "License dang rong. Hay dien License=... trong AutoNapLic.txt"
    }
    $skipStartupPopups = $config["SkipStartupPopups"].ToLowerInvariant() -ne "false"

    if (-not (Test-IsAdmin)) {
        Write-Host "Can quyen Administrator de nap ID vao Registry va bam nut Ap dung."
        Write-Log "Restarting as Administrator."
        $scriptPath = $MyInvocation.MyCommand.Path
        $argsList = "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -BaseDir `"$BaseDir`" -ConfigFile `"$ConfigFile`""
        Start-Process -FilePath "powershell.exe" -ArgumentList $argsList -Verb RunAs
        exit 0
    }

    $exePath = Find-ExePath $config $BaseDir
    Write-Log "ExePath: $exePath"
    Write-RegistryValue $license $skipStartupPopups
    Write-LicenseFiles $exePath $license

    $autoStart = $config["AutoStart"].ToLowerInvariant() -ne "false"
    $applyAfterFill = $config["ApplyAfterFill"].ToLowerInvariant() -ne "false"
    $waitSeconds = 5
    try { $waitSeconds = [int]$config["WaitSeconds"] } catch { $waitSeconds = 5 }
    if ($waitSeconds -lt 1) { $waitSeconds = 1 }
    $maxAttempts = 5
    try { $maxAttempts = [int]$config["MaxAttempts"] } catch { $maxAttempts = 5 }
    if ($maxAttempts -lt 1) { $maxAttempts = 1 }
    if ($maxAttempts -gt 5) { $maxAttempts = 5 }
    $attemptDelaySeconds = 3
    try { $attemptDelaySeconds = [int]$config["AttemptDelaySeconds"] } catch { $attemptDelaySeconds = 3 }
    if ($attemptDelaySeconds -lt 1) { $attemptDelaySeconds = 1 }
    if ($attemptDelaySeconds -gt 10) { $attemptDelaySeconds = 10 }

    if ($autoStart) {
        $exeDir = [IO.Path]::GetDirectoryName($exePath)
        Start-LiteralProcess $exePath $exeDir
        Write-Log "Started auto."
        Start-Sleep -Seconds $waitSeconds
    }

    if ($applyAfterFill) {
        $processNames = $config["ProcessNames"].Split(",")
        $filled = 0
        for ($attempt = 1; $attempt -le $maxAttempts -and $filled -le 0; $attempt++) {
            Write-Log "UI fill attempt: $attempt/$maxAttempts"
            $filled = Set-LicenseInAutoWindow $license $processNames
            if ($filled -le 0) {
                Start-Sleep -Seconds $attemptDelaySeconds
            }
        }
        Write-Log "UI fill result: $filled"
        if ($filled -le 0) {
            Write-WindowSnapshot
            $requireApplySuccess = $config["RequireApplySuccess"].ToLowerInvariant() -eq "true"
            if ($requireApplySuccess) {
                throw "Mo Auto That bai lien he Support de ho tro."
            }
            Write-Host "Khong tim thay cua so auto de tu dien lic. Da ghi log, khong xem la loi mo auto."
            Write-Log "UI fill skipped as soft failure. RequireApplySuccess=false."
        }
        else {
            Write-Host "Da tu dien va bam Ap dung cho $filled cua so auto."
        }
    }
    else {
        Write-Host "Da nap file va registry. ApplyAfterFill=false nen khong bam UI."
        Write-Log "ApplyAfterFill=false."
    }

    Write-Log "===== Done ====="
}
catch {
    Write-Host $_.Exception.Message
    Write-Log ("ERROR: {0}" -f $_.Exception.Message)
    Show-FailMessage "Mo Auto That bai lien he Support de ho tro."
    exit 1
}
finally {
    try {
        $self = $MyInvocation.MyCommand.Path
        if ($self -like (Join-Path $env:TEMP "AutoNapLic_*.ps1")) {
            Remove-Item -LiteralPath $self -Force -ErrorAction SilentlyContinue
        }
    }
    catch {
    }
}
