IntuneQL.psm1

function Ensure-GraphAuthModule {
    [OutputType([bool])]
    param()

    $moduleName = 'Microsoft.Graph.Authentication'

    # Check if module is installed
    $installed = Get-Module -ListAvailable $moduleName | Sort-Object Version -Descending | Select-Object -First 1

    if (-not $installed) {
        Write-Host "Microsoft.Graph.Authentication is not installed. Installing..." -ForegroundColor Yellow
        try {
            Install-Module $moduleName -Scope CurrentUser -Force -AllowClobber -Repository PSGallery
            Write-Host "Microsoft.Graph.Authentication installed successfully." -ForegroundColor Green
        } catch {
            Write-Error "Failed to install Microsoft.Graph.Authentication: $_"
            Write-Error "Run manually: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser"
            return $false
        }
    } else {
        # Check for updates (max once per 24 hours)
        $dir = Join-Path $HOME ".intuneql"
        if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
        $stampFile = Join-Path $dir ".last-update-check"

        $shouldCheck = $true
        if (Test-Path $stampFile) {
            $lastCheck = Get-Content $stampFile -ErrorAction SilentlyContinue
            if ($lastCheck) {
                try {
                    $lastDate = [datetime]::Parse($lastCheck)
                    if ((Get-Date) - $lastDate -lt [TimeSpan]::FromHours(24)) {
                        $shouldCheck = $false
                    }
                } catch { }
            }
        }

        if ($shouldCheck) {
            try {
                $online = Find-Module $moduleName -Repository PSGallery -ErrorAction Stop
                if ($online.Version -gt $installed.Version) {
                    Write-Host "Updating Microsoft.Graph.Authentication ($($installed.Version) -> $($online.Version))..." -ForegroundColor Yellow
                    Update-Module $moduleName -Scope CurrentUser -Force -ErrorAction Stop
                    Write-Host "Microsoft.Graph.Authentication updated successfully." -ForegroundColor Green
                }
            } catch {
                Write-Warning "Could not check for Microsoft.Graph.Authentication updates: $_"
            }
            # Write stamp regardless of outcome so we don't retry every launch
            Set-Content $stampFile (Get-Date).ToString("o") -Force -ErrorAction SilentlyContinue
        }
    }

    return $true
}

function Start-IntuneQL {
    [CmdletBinding()]
    param(
        [switch]$Library
    )

    # Ensure Microsoft.Graph.Authentication is installed and up to date
    if (-not (Ensure-GraphAuthModule)) {
        return
    }

    # Detect OS and arch
    $os = if ($IsWindows -or $PSVersionTable.PSVersion.Major -lt 6) {
        'windows'
    } elseif ($IsMacOS) {
        'darwin'
    } else {
        'linux'
    }

    $arch = switch ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture) {
        'Arm64' { 'arm64' }
        default { 'amd64' }
    }

    $binName = "intuneql-$os-$arch"
    if ($os -eq 'windows') { $binName += '.exe' }
    $binPath = Join-Path $PSScriptRoot 'bin' $binName

    if (-not (Test-Path $binPath)) {
        Write-Error "Binary not found: $binPath. Try: Update-Module IntuneQL"
        return
    }

    if ($os -ne 'windows') {
        & chmod +x $binPath 2>$null
    }

    # Auth via Microsoft.Graph.Authentication
    Import-Module Microsoft.Graph.Authentication -ErrorAction Stop

    $ctx = Get-MgContext
    if (-not $ctx) {
        $scopes = @(
            "DeviceManagementManagedDevices.Read.All",
            "DeviceManagementManagedDevices.ReadWrite.All",
            "DeviceManagementConfiguration.Read.All",
            "DeviceManagementApps.Read.All",
            "DeviceManagementServiceConfig.Read.All",
            "DeviceManagementRBAC.Read.All",
            "CloudPC.Read.All",
            "DeviceManagementScripts.Read.All"
        )
        Connect-MgGraph -Scopes $scopes -NoWelcome
        $ctx = Get-MgContext
    }

    if (-not $ctx) {
        Write-Error "Failed to authenticate with Microsoft Graph. Please try again."
        return
    }

    try {
        if (Get-Command 'Get-MgAccessToken' -ErrorAction SilentlyContinue) {
            $tokenResponse = Get-MgAccessToken -ResourceUrl "https://graph.microsoft.com"
            $token = if ($tokenResponse -is [string]) { $tokenResponse } else { $tokenResponse.AccessToken }
        } else {
            # Fallback for older Microsoft.Graph.Authentication (v1.x)
            $resp = Invoke-MgGraphRequest -Uri 'https://graph.microsoft.com/v1.0/organization?$select=id' -Method GET -OutputType HttpResponseMessage
            $token = $resp.RequestMessage.Headers.Authorization.Parameter
        }

        $tokenData = @{
            token      = $token
            expiresAt  = (Get-Date).AddMinutes(50).ToString("o")
            tenantId   = $ctx.TenantId
            userUpn    = $ctx.Account
            scopes     = @($ctx.Scopes)
            isConnected = $true
            authMethod = "msgraph"
        } | ConvertTo-Json -Depth 3

        $dir = Join-Path $HOME ".intuneql"
        if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
        if (-not $IsWindows) { & chmod 700 $dir 2>$null }
        $tokenPath = Join-Path $dir "token.json"
        Set-Content $tokenPath $tokenData -Force
        if (-not $IsWindows) { & chmod 600 $tokenPath 2>$null }

        $env:INTUNEQL_AUTH = "msgraph"
    } catch {
        Write-Error "Failed to get access token: $_"
        return
    }

    # Build args
    $binArgs = @()
    if ($Library) { $binArgs += '--mode=library' }

    & $binPath @binArgs
}

New-Alias -Name 'IntuneQL' -Value 'Start-IntuneQL' -Force

Export-ModuleMember -Function 'Start-IntuneQL' -Alias 'IntuneQL'