#Requires -RunAsAdministrator

[CmdletBinding()]
param(
    [switch]$SkipBloatware,
    [switch]$SkipSoftware,
    [switch]$SkipDefaultProfile,
    [switch]$DryRun,
    [ValidateSet("default","admin","user")]
    [string]$ProfileType = "default"
)

$ErrorActionPreference = "Continue"

# -----------------------------------------------------------------------
# Paths
# -----------------------------------------------------------------------
$ScriptRoot  = $PSScriptRoot
$LogDir      = "C:\Windows\Setup\Scripts"
$LogFile     = "$LogDir\Deploy.log"
$ConfigFile  = "$ScriptRoot\config\config.json"

# -----------------------------------------------------------------------
# Logging
# -----------------------------------------------------------------------
function Write-Log {
    param(
        [string]$Message,
        [ValidateSet("INFO","OK","ERROR","WARN","STEP")]
        [string]$Level = "INFO"
    )
    $timestamp = Get-Date -Format "HH:mm:ss"
    $line = "[$timestamp] [$Level] $Message"
    Add-Content -Path $LogFile -Value $line -Encoding UTF8
    switch ($Level) {
        "OK"    { Write-Host $line -ForegroundColor Green }
        "ERROR" { Write-Host $line -ForegroundColor Red }
        "WARN"  { Write-Host $line -ForegroundColor Yellow }
        "STEP"  { Write-Host $line -ForegroundColor Cyan }
        default { Write-Host $line }
    }
}

# -----------------------------------------------------------------------
# Step runner - catches errors, logs, always continues
# -----------------------------------------------------------------------
$StepResults = [System.Collections.Generic.List[hashtable]]::new()

function Invoke-Step {
    param(
        [string]$Name,
        [scriptblock]$Action
    )

    Write-Log "---- $Name ----" -Level STEP

    if ($DryRun) {
        Write-Log "DryRun - skipping execution" -Level WARN
        $StepResults.Add(@{ Name = $Name; Status = "DRYRUN" })
        return
    }

    try {
        & $Action
        Write-Log "$Name - OK" -Level OK
        $StepResults.Add(@{ Name = $Name; Status = "OK" })
    }
    catch {
        Write-Log "$Name - ERROR: $_" -Level ERROR
        $StepResults.Add(@{ Name = $Name; Status = "ERROR" })
    }
}

# -----------------------------------------------------------------------
# Init
# -----------------------------------------------------------------------
if (-not (Test-Path $LogDir)) {
    New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
}

Write-Log "========================================" -Level INFO
Write-Log "Deploy-Windows.ps1 started" -Level INFO
Write-Log "Computer: $env:COMPUTERNAME" -Level INFO
Write-Log "User: $env:USERNAME" -Level INFO
Write-Log "Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -Level INFO
if ($DryRun) { Write-Log "Mode: DRY RUN" -Level WARN }
Write-Log "========================================" -Level INFO

# -----------------------------------------------------------------------
# Load config
# -----------------------------------------------------------------------
$Config = $null
Invoke-Step -Name "Load config.json" -Action {
    if (-not (Test-Path $ConfigFile)) {
        throw "config.json not found: $ConfigFile"
    }
    $script:Config = Get-Content $ConfigFile -Raw -Encoding UTF8 | ConvertFrom-Json
    Write-Log "Config loaded from $ConfigFile" -Level INFO
}

# -----------------------------------------------------------------------
# Build step enable/disable map from config + CLI overrides
# -----------------------------------------------------------------------
$stepsEnabled = @{
    adminAccount    = $true
    bloatware       = $true
    software        = $true
    systemRegistry  = $true
    defaultProfile  = $true
    personalization = $true
    scheduledTasks  = $true
    backinfo        = $true
    network         = $true
    pcIdentity      = $true
    activation      = $true
    dellUpdate      = $true
}
if ($Config -and $Config.steps) {
    foreach ($key in @($stepsEnabled.Keys)) {
        $val = $Config.steps.$key
        if ($null -ne $val) { $stepsEnabled[$key] = [bool]$val }
    }
}
# CLI switches override config.steps
if ($SkipBloatware)      { $stepsEnabled['bloatware']      = $false }
if ($SkipSoftware)       { $stepsEnabled['software']       = $false }
if ($SkipDefaultProfile) { $stepsEnabled['defaultProfile'] = $false }

function Skip-Step {
    param([string]$Name)
    Write-Log "$Name - SKIPPED (disabled in config)" -Level WARN
    $StepResults.Add(@{ Name = $Name; Status = "SKIPPED" })
}

# -----------------------------------------------------------------------
# Step 0a - Admin account
# -----------------------------------------------------------------------
if ($stepsEnabled['adminAccount']) {
    Invoke-Step -Name "Step 0a - Admin account" -Action {
        & "$ScriptRoot\scripts\00-admin-account.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 0a - Admin account" }

# -----------------------------------------------------------------------
# Step 0b - Windows activation
# -----------------------------------------------------------------------
if ($stepsEnabled['activation']) {
    Invoke-Step -Name "Step 0b - Windows activation" -Action {
        & "$ScriptRoot\scripts\08-activation.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 0b - Windows activation" }

# -----------------------------------------------------------------------
# Step 1 - Bloatware removal
# -----------------------------------------------------------------------
if ($stepsEnabled['bloatware']) {
    Invoke-Step -Name "Step 1 - Bloatware removal" -Action {
        & "$ScriptRoot\scripts\01-bloatware.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 1 - Bloatware removal" }

# -----------------------------------------------------------------------
# Step 2 - Software installation
# -----------------------------------------------------------------------
if ($stepsEnabled['software']) {
    Invoke-Step -Name "Step 2 - Software installation" -Action {
        & "$ScriptRoot\scripts\02-software.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 2 - Software installation" }

# -----------------------------------------------------------------------
# Step 3 - System registry (HKLM)
# -----------------------------------------------------------------------
if ($stepsEnabled['systemRegistry']) {
    Invoke-Step -Name "Step 3 - System registry" -Action {
        & "$ScriptRoot\scripts\03-system-registry.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 3 - System registry" }

# -----------------------------------------------------------------------
# Step 4 - Default profile (NTUSER.DAT)
# -----------------------------------------------------------------------
if ($stepsEnabled['defaultProfile']) {
    Invoke-Step -Name "Step 4 - Default profile" -Action {
        & "$ScriptRoot\scripts\04-default-profile.ps1" -Config $Config -LogFile $LogFile -ProfileType $ProfileType
    }
} else { Skip-Step "Step 4 - Default profile" }

# -----------------------------------------------------------------------
# Step 5 - Personalization
# -----------------------------------------------------------------------
if ($stepsEnabled['personalization']) {
    Invoke-Step -Name "Step 5 - Personalization" -Action {
        & "$ScriptRoot\scripts\05-personalization.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 5 - Personalization" }

# -----------------------------------------------------------------------
# Step 6 - Scheduled tasks
# -----------------------------------------------------------------------
if ($stepsEnabled['scheduledTasks']) {
    Invoke-Step -Name "Step 6 - Scheduled tasks" -Action {
        & "$ScriptRoot\scripts\06-scheduled-tasks.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 6 - Scheduled tasks" }

# -----------------------------------------------------------------------
# Step 7 - BackInfo
# -----------------------------------------------------------------------
if ($stepsEnabled['backinfo']) {
    Invoke-Step -Name "Step 7 - BackInfo" -Action {
        & "$ScriptRoot\scripts\07-backinfo.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 7 - BackInfo" }

# -----------------------------------------------------------------------
# Step 9 - Network
# -----------------------------------------------------------------------
if ($stepsEnabled['network']) {
    Invoke-Step -Name "Step 9 - Network" -Action {
        & "$ScriptRoot\scripts\10-network.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 9 - Network" }

# -----------------------------------------------------------------------
# Step 11 - Dell Command | Update (auto-skipped on non-Dell hardware)
# -----------------------------------------------------------------------
if ($stepsEnabled['dellUpdate']) {
    Invoke-Step -Name "Step 11 - Dell Command | Update" -Action {
        & "$ScriptRoot\scripts\11-dell-update.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 11 - Dell Command | Update" }

# -----------------------------------------------------------------------
# Step 10 - PC identity (rename + C:\X9) - runs last, rename needs restart
# -----------------------------------------------------------------------
if ($stepsEnabled['pcIdentity']) {
    Invoke-Step -Name "Step 10 - PC identity" -Action {
        & "$ScriptRoot\scripts\09-pc-identity.ps1" -Config $Config -LogFile $LogFile
    }
} else { Skip-Step "Step 10 - PC identity" }

# -----------------------------------------------------------------------
# Summary
# -----------------------------------------------------------------------
Write-Log "========================================" -Level INFO
Write-Log "SUMMARY" -Level INFO
Write-Log "========================================" -Level INFO

$countOK      = ($StepResults | Where-Object { $_.Status -eq "OK"      }).Count
$countError   = ($StepResults | Where-Object { $_.Status -eq "ERROR"   }).Count
$countSkipped = ($StepResults | Where-Object { $_.Status -eq "SKIPPED" }).Count
$countDryRun  = ($StepResults | Where-Object { $_.Status -eq "DRYRUN"  }).Count

foreach ($r in $StepResults) {
    $lvl = switch ($r.Status) {
        "OK"      { "OK" }
        "ERROR"   { "ERROR" }
        "SKIPPED" { "WARN" }
        "DRYRUN"  { "WARN" }
    }
    Write-Log "$($r.Status.PadRight(8)) $($r.Name)" -Level $lvl
}

Write-Log "----------------------------------------" -Level INFO
Write-Log "OK: $countOK  ERROR: $countError  SKIPPED: $countSkipped  DRYRUN: $countDryRun" -Level INFO
Write-Log "Log saved to: $LogFile" -Level INFO
Write-Log "========================================" -Level INFO

if ($countError -gt 0) {
    Write-Log "Deployment finished with errors. Review log: $LogFile" -Level ERROR
    exit 1
} else {
    Write-Log "Deployment finished successfully." -Level OK
    exit 0
}
