param (
    [Parameter(Mandatory=$true)]
    [string]$DriveLetter
)

$ErrorActionPreference = "SilentlyContinue"
$letra = $DriveLetter.TrimEnd(':').ToUpper()

Write-Host "Expulsando unidad ${letra}:..."

# ─── MÉTODO 1: IMAPI2 (más confiable, funciona sin GUI) ──────────────────────
$ok = $false
try {
    $m = New-Object -ComObject IMAPI2.MsftDiscMaster2
    foreach ($id in $m) {
        $r = New-Object -ComObject IMAPI2.MsftDiscRecorder2
        $r.InitializeDiscRecorder($id)
        if ($r.DriveLetter -eq "${letra}:") {
            $r.EjectMedia()
            Write-Host "EJECT_OK: IMAPI2"
            $ok = $true
            break
        }
    }
} catch {
    Write-Host "IMAPI2 fallo: $_"
}

if ($ok) { exit 0 }

# ─── MÉTODO 2: WMI Win32_CDROMDrive ──────────────────────────────────────────
try {
    $drives = Get-WmiObject Win32_CDROMDrive -ErrorAction Stop
    foreach ($d in $drives) {
        # Comparar la letra de unidad
        if ($d.Id -eq "${letra}:") {
            # Abrir/cerrar la bandeja via DeviceIoControl (fsutil)
            # Usamos el método nativo del COM de Shell como fallback
            $shell = New-Object -ComObject "Shell.Application"
            $folder = $shell.Namespace(17)  # ssfDrives = 17
            if ($folder) {
                $item = $folder.ParseName("${letra}:")
                if ($item) {
                    $item.InvokeVerb("Eject")
                    Start-Sleep -Milliseconds 500
                    Write-Host "EJECT_OK: Shell.Application"
                    $ok = $true
                    break
                }
            }
        }
    }
} catch {
    Write-Host "WMI/Shell fallo: $_"
}

if ($ok) { exit 0 }

# ─── MÉTODO 3: Comando nativo de Windows (diskutil) ──────────────────────────
try {
    # Usar el comando de PowerShell para enviar el código DeviceIoControl directo
    $source = @"
using System;
using System.Runtime.InteropServices;
public class CdRom {
    [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
        uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
        uint dwFlagsAndAttributes, IntPtr hTemplateFile);
    [DllImport("kernel32.dll", ExactSpelling=true, SetLastError=true, CharSet=CharSet.Auto)]
    public static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
        IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize,
        out uint lpBytesReturned, IntPtr lpOverlapped);
    [DllImport("kernel32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CloseHandle(IntPtr hObject);
    public static void Eject(string drive) {
        IntPtr h = CreateFile(@"\\.\" + drive, 0xC0000000, 3, IntPtr.Zero, 3, 0, IntPtr.Zero);
        if (h.ToInt32() == -1) throw new Exception("No se pudo abrir el drive");
        uint bytes = 0;
        DeviceIoControl(h, 0x2D4808, IntPtr.Zero, 0, IntPtr.Zero, 0, out bytes, IntPtr.Zero); // IOCTL_STORAGE_EJECT_MEDIA
        CloseHandle(h);
    }
}
"@
    Add-Type -TypeDefinition $source -Language CSharp -ErrorAction Stop
    [CdRom]::Eject("${letra}:")
    Write-Host "EJECT_OK: DeviceIoControl"
    $ok = $true
} catch {
    Write-Host "DeviceIoControl fallo: $_"
}

if ($ok) { exit 0 }

Write-Host "EJECT_FAIL: Todos los metodos fallaron para ${letra}:"
exit 1
