<#
Nama Script   : EmptyIndexDestroyer.ps1
Deskripsi     :
Script ini mencari dan menghapus file index.md yang memiliki konten kosong atau
hanya berisi frontmatter kosong dari direktori yang dipilih user, dengan opsi
kedalaman folder.

Alur User     :
1. User memasukkan path folder target.
2. Script validasi path, jika tidak ada minta ulang.
3. User bisa ganti nama file target (default: index.md) atau Enter untuk pakai default.
4. User pilih scope:
   - Y  : Semua subfolder (rekursif penuh)
   - N  : Batal, kembali ke input path
   - Angka : Sampai level kedalaman tertentu
5. Script preview dulu file empty yang akan di-delete (dry run tampilan).
6. User konfirmasi Y/N sebelum eksekusi.
7. Script hapus file dan tampilkan summary.

File dianggap EMPTY jika:
- File size 0 byte
- Hanya berisi whitespace
- Hanya berisi frontmatter kosong (---, ---)
- Hanya berisi frontmatter dengan whitespace/newlines saja
#>

# ── Shell.Application untuk Recycle Bin ───────────────────────────────────────
$shell = New-Object -ComObject Shell.Application

function Move-ToRecycleBin {
    param ([string]$FilePath)
    try {
        $item = $shell.Namespace(0).ParseName((Resolve-Path $FilePath).Path)
        if ($item) {
            $item.InvokeVerb("delete")
            return $true
        }
        return $false
    }
    catch {
        return $false
    }
}

# ── Check if file is empty (including empty frontmatter) ──────────────────────
function Test-EmptyIndexFile {
    param ([string]$FilePath)

    try {
        # Check file size
        $fileInfo = Get-Item $FilePath -ErrorAction Stop
        
        if ($fileInfo.Length -eq 0) {
            return $true
        }

        # Read content
        $content = Get-Content $FilePath -Raw -ErrorAction Stop

        # Check if only whitespace
        if ([string]::IsNullOrWhiteSpace($content)) {
            return $true
        }

        # Check for empty frontmatter pattern (---, ---)
        # Pattern: starts with ---, then only whitespace/newlines, then ---
        if ($content -match '^\s*---\s*---\s*$') {
            return $true
        }

        # Pattern: starts with ---, then only whitespace, then ---, then only whitespace
        if ($content -match '^\s*---[\s\n]*---\s*$') {
            return $true
        }

        # Pattern: frontmatter block only (---, content with only whitespace, ---)
        $lines = $content -split "`n"
        
        if ($lines.Count -ge 2 -and $lines[0].Trim() -eq '---') {
            # Find closing ---
            $closingIndex = -1
            for ($i = 1; $i -lt $lines.Count; $i++) {
                if ($lines[$i].Trim() -eq '---') {
                    $closingIndex = $i
                    break
                }
            }

            # If closing --- found
            if ($closingIndex -gt 0) {
                # Check if frontmatter content is only whitespace
                $frontmatterContent = $lines[1..$($closingIndex - 1)] -join "`n"
                
                # Check if anything after closing ---
                if ($closingIndex -eq $lines.Count - 1) {
                    # Nothing after ---, check if frontmatter is empty
                    if ([string]::IsNullOrWhiteSpace($frontmatterContent)) {
                        return $true
                    }
                } else {
                    # Something after closing ---, check if it's only whitespace
                    $afterFrontmatter = $lines[($closingIndex + 1)..$($lines.Count - 1)] -join "`n"
                    if ([string]::IsNullOrWhiteSpace($frontmatterContent) -and [string]::IsNullOrWhiteSpace($afterFrontmatter)) {
                        return $true
                    }
                }
            }
        }

        return $false
    }
    catch {
        return $false
    }
}

# ── Collect empty files sampai level tertentu ─────────────────────────────────
function Get-EmptyTargetFiles {
    param (
        [string]$Path,
        [string]$FileName,
        [int]$Level = 0,
        [int]$MaxLevel = -1   # -1 = unlimited
    )

    $results = @()

    # Cek file di level ini
    $filePath = Join-Path $Path $FileName
    if ((Test-Path $filePath -PathType Leaf) -and (Test-EmptyIndexFile $filePath)) {
        $results += $filePath
    }

    # Stop kalau sudah capai max level
    if ($MaxLevel -ne -1 -and $Level -ge $MaxLevel) {
        return $results
    }

    # Rekursi ke subfolder
    $subFolders = Get-ChildItem -Path $Path -Directory -ErrorAction SilentlyContinue | Sort-Object Name
    foreach ($folder in $subFolders) {
        $results += Get-EmptyTargetFiles -Path $folder.FullName -FileName $FileName -Level ($Level + 1) -MaxLevel $MaxLevel
    }

    return $results
}

# ── Print tree preview dengan highlight file target yang empty ────────────────
function Print-PreviewTree {
    param (
        [string]$Path,
        [string]$FileName,
        [int]$Level = 0,
        [int]$MaxLevel = -1,
        [ref]$FoundCount
    )

    if ($MaxLevel -ne -1 -and $Level -ge $MaxLevel) { return }

    $indent = "  " * $Level

    # Cek apakah ada file target EMPTY di folder ini
    $filePath = Join-Path $Path $FileName
    if ((Test-Path $filePath -PathType Leaf) -and (Test-EmptyIndexFile $filePath)) {
        $fileSize = (Get-Item $filePath).Length
        Write-Host "$indent  🗑️  $FileName" -ForegroundColor Red -NoNewline
        Write-Host " (${fileSize} bytes)" -ForegroundColor DarkRed
        $FoundCount.Value++
    }

    $subFolders = Get-ChildItem -Path $Path -Directory -ErrorAction SilentlyContinue | Sort-Object Name
    foreach ($folder in $subFolders) {
        Write-Host "$indent  📁 $($folder.Name)" -ForegroundColor DarkGray
        Print-PreviewTree -Path $folder.FullName -FileName $FileName -Level ($Level + 1) -MaxLevel $MaxLevel -FoundCount $FoundCount
    }
}

# ── Banner ─────────────────────────────────────────────────────────────────────
Clear-Host
Write-Host "╔══════════════════════════════════════════════╗" -ForegroundColor DarkRed
Write-Host "║    🗑️   EMPTY INDEX DESTROYER  v1.0          ║" -ForegroundColor DarkRed
Write-Host "║  Delete empty index.md files by depth level  ║" -ForegroundColor DarkRed
Write-Host "╚══════════════════════════════════════════════╝" -ForegroundColor DarkRed
Write-Host ""

# ── MAIN LOOP ─────────────────────────────────────────────────────────────────
do {

    # ── Step 1: Input path ────────────────────────────────────────────────────
    do {
        $targetFolder = Read-Host "📂 Masukkan path folder target (contoh: D:\MyProject)"
        $targetFolder = $targetFolder.Trim('"').Trim("'").Trim()

        if (-not (Test-Path $targetFolder -PathType Container)) {
            Write-Host "`n❌ Path tidak ditemukan atau bukan folder. Periksa kembali!`n" -ForegroundColor Red
            $validPath = $false
        } else {
            $validPath = $true
        }
    } while (-not $validPath)

    # ── Step 2: Input nama file target ────────────────────────────────────────
    Write-Host ""
    $inputFileName = Read-Host "📄 Nama file target (Enter = pakai default 'index.md')"
    $inputFileName = $inputFileName.Trim()

    if ([string]::IsNullOrWhiteSpace($inputFileName)) {
        $targetFileName = "index.md"
    } else {
        $targetFileName = $inputFileName
    }

    Write-Host "  → Target file: " -NoNewline
    Write-Host $targetFileName -ForegroundColor Cyan

    # ── Step 3: Pilih scope / kedalaman ───────────────────────────────────────
    $restartToPath = $false

    do {
        Write-Host ""
        $inputLevel = Read-Host "🔍 Scope pencarian? (Y = semua subfolder, N = batal, atau angka level kedalaman)"
        $inputLevel = $inputLevel.Trim().ToLower()

        if ($inputLevel -eq 'n') {
            Write-Host "`n⚠️  Dibatalkan. Kembali ke pemilihan folder...`n" -ForegroundColor Yellow
            $restartToPath = $true
            break
        }
        elseif ($inputLevel -eq 'y') {
            $maxLevel = -1
            $scopeLabel = "semua subfolder (rekursif penuh)"
            $validScope = $true
        }
        elseif ([int]::TryParse($inputLevel, [ref]$null)) {
            $maxLevel = [int]$inputLevel
            if ($maxLevel -le 0) {
                Write-Host "⚠️  Masukkan angka lebih besar dari 0." -ForegroundColor Yellow
                $validScope = $false
            } else {
                $scopeLabel = "kedalaman level $maxLevel"
                $validScope = $true
            }
        }
        else {
            Write-Host "❌ Input tidak valid. Masukkan 'Y', 'N', atau angka." -ForegroundColor Red
            $validScope = $false
        }
    } while (-not $validScope -and -not $restartToPath)

    if ($restartToPath) { continue }

    # ── Step 4: Preview / Dry Run ─────────────────────────────────────────────
    Write-Host ""
    Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray
    Write-Host "🔎 PREVIEW — File EMPTY yang akan dihapus:" -ForegroundColor Yellow
    Write-Host "   Folder  : $targetFolder" -ForegroundColor Gray
    Write-Host "   File    : $targetFileName" -ForegroundColor Gray
    Write-Host "   Scope   : $scopeLabel" -ForegroundColor Gray
    Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray
    Write-Host ""

    $foundCount = [ref]0
    Write-Host "📁 $targetFolder" -ForegroundColor White
    Print-PreviewTree -Path $targetFolder -FileName $targetFileName -MaxLevel $maxLevel -FoundCount $foundCount

    Write-Host ""
    Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray

    if ($foundCount.Value -eq 0) {
        Write-Host "✅ Tidak ada file '$targetFileName' kosong yang ditemukan dalam scope ini." -ForegroundColor Green
        Write-Host ""
        $retry = Read-Host "🔁 Coba folder/file lain? (Y = ya, N = keluar)"
        if ($retry.Trim().ToLower() -ne 'y') {
            break
        } else {
            continue
        }
    }

    Write-Host "📊 Total ditemukan: " -NoNewline
    Write-Host "$($foundCount.Value) file EMPTY" -ForegroundColor Red -NoNewline
    Write-Host " akan dihapus."
    Write-Host ""

    # ── Step 5: Konfirmasi eksekusi ───────────────────────────────────────────
    $confirm = Read-Host "⚠️  Lanjutkan? File akan dihapus ke Recycle Bin (Y/N)"
    $confirm = $confirm.Trim().ToLower()

    if ($confirm -ne 'y') {
        Write-Host "`n❌ Dibatalkan. Tidak ada file yang dihapus.`n" -ForegroundColor Yellow
        $retry = Read-Host "🔁 Coba lagi? (Y = ya, N = keluar)"
        if ($retry.Trim().ToLower() -ne 'y') { break } else { continue }
    }

    # ── Step 6: Eksekusi ──────────────────────────────────────────────────────
    Write-Host ""
    Write-Host "🚀 Menghapus file empty..." -ForegroundColor Cyan

    $filesToDelete = Get-EmptyTargetFiles -Path $targetFolder -FileName $targetFileName -MaxLevel $maxLevel
    $successCount = 0
    $failCount    = 0
    $failedFiles  = @()

    foreach ($file in $filesToDelete) {
        try {
            if (Move-ToRecycleBin $file) {
                Write-Host "  ✅ Deleted → $file" -ForegroundColor Green
                $successCount++
            } else {
                throw "Failed to move to recycle bin"
            }
        }
        catch {
            Write-Host "  ❌ Gagal  → $file" -ForegroundColor Red
            $failCount++
            $failedFiles += $file
        }
    }

    # ── Step 7: Summary ───────────────────────────────────────────────────────
    Write-Host ""
    Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray
    Write-Host "📊 SUMMARY" -ForegroundColor White
    Write-Host "   ✅ Berhasil dihapus  : $successCount file" -ForegroundColor Green
    if ($failCount -gt 0) {
        Write-Host "   ❌ Gagal             : $failCount file" -ForegroundColor Red
        foreach ($f in $failedFiles) {
            Write-Host "      - $f" -ForegroundColor DarkRed
        }
    }
    Write-Host "   🗑️  Semua file ada di Recycle Bin — bisa di-restore kalau perlu." -ForegroundColor DarkGray
    Write-Host "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor DarkGray
    Write-Host ""

    # ── Selesai / ulangi ──────────────────────────────────────────────────────
    $again = Read-Host "🔁 Destroy folder/file lain? (Y = ya, N = keluar)"
    if ($again.Trim().ToLower() -ne 'y') { break }

} while ($true)

Write-Host ""
Write-Host "👋 EmptyIndexDestroyer selesai. Sampai jumpa!" -ForegroundColor DarkCyan
Write-Host ""