# Ensure Microsoft.Graph module is installed
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph)) {
    Write-Host "Installing Microsoft.Graph module..."
    Install-Module -Name Microsoft.Graph -Force -AllowClobber
}

# Import necessary modules
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Applications

# Connect to Microsoft Graph with required permissions
Connect-MgGraph -Scopes "Application.ReadWrite.All", "Directory.ReadWrite.All", "AppRoleAssignment.ReadWrite.All" -NoWelcome

# Application details
$Name = "GraphAPI"
$Scope = "User.Read.All", "User.ReadWrite.All", "Group.Read.All", "Group.ReadWrite.All"

# Fetch Microsoft Graph Service Principal
$graphSp = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'"
$graphRoles = $graphSp.AppRoles

# Debugging: Confirm AppRoles permissions
# Write-Host "`nšŸ” Retrieved AppRoles from Microsoft Graph:"
# $graphRoles | Format-Table DisplayName, Id, Value -AutoSize

# Build required resource access list
$resourceAccess = @()
foreach ($perm in $Scope) {
    $permId = ($graphRoles | Where-Object { $_.Value -eq $perm }).Id
    if ($permId) {
        $resourceAccess += @{
            "id"   = $permId
            "Type" = "Role"  # Use "Scope" if using delegated permissions
        }
    } else {
        Write-Host "āš ļø Skipping $perm - Role ID not found in Microsoft Graph."
    }
}

# Debugging: Confirm matched permissions
# Write-Host "`nāœ… Final Mapped Permissions:"
# $resourceAccess | Format-Table -AutoSize

# Define app creation body
$body = @{
    DisplayName            = $Name
    SignInAudience         = "AzureADMyOrg"
    RequiredResourceAccess = @(
        @{
            ResourceAppId  = "00000003-0000-0000-c000-000000000000"  # Microsoft Graph
            ResourceAccess = $resourceAccess
        }
    )
}

# Convert body to JSON
$payload = $body | ConvertTo-Json -Depth 4

# Create the application
Write-Host "Creating Azure AD application..."
$app = New-MgApplication -BodyParameter $payload

if (-not $app) {
    Write-Host "āŒ Failed to create application. Exiting."
    exit
}

Write-Host "āœ… Application Created: $($app.Id)"

# Wait for the application to propagate
Start-Sleep -Seconds 10
Write-Host "ā³ Waiting for application propagation..."

# Create Service Principal
Write-Host "Creating Service Principal..."
$servicePrincipal = New-MgServicePrincipal -AppId $app.AppId

if (-not $servicePrincipal) {
    Write-Host "āŒ Failed to create Service Principal. Exiting."
    exit
}

Write-Host "āœ… Service Principal created: $($servicePrincipal.Id)"

# Wait for service principal to propagate
Start-Sleep -Seconds 10
Write-Host "ā³ Waiting for application permissions to propagate..."

# Grant Admin Consent
foreach ($access in $resourceAccess) {
    # Write-Host "`nšŸ”¹ About to grant admin consent for:"
    # Write-Host "   āžœ AppRoleId: $($access.id)"
    # Write-Host "   āžœ ServicePrincipalId: $($servicePrincipal.Id)"
    # Write-Host "   āžœ PrincipalId: $($servicePrincipal.Id)"
    # Write-Host "   āžœ ResourceId: $($graphSp.Id)"

    try {
        $null = New-MgServicePrincipalAppRoleAssignment `
            -ServicePrincipalId $servicePrincipal.Id `
            -PrincipalId $servicePrincipal.Id `
            -ResourceId $graphSp.Id `
            -AppRoleId $access.id
        
        Write-Host "āœ… Successfully granted admin consent for AppRoleId: $($access.id)"
    } catch {
        Write-Host "āŒ Failed to grant admin consent for AppRoleId: $($access.id) - $_"
    }
}

Write-Host "`nšŸŽ‰ Admin consent process completed!"

# -------------------------------
# CREATE CLIENT SECRET
# -------------------------------

Write-Host "`nšŸ” Creating Client Secret..."
$secretStartDate = Get-Date
$secretEndDate = $secretStartDate.AddYears(1)  # Secret valid for 1 year

$clientSecret = Add-MgApplicationPassword -ApplicationId $app.Id -PasswordCredential @{
    DisplayName = "GraphAPI-ClientSecret"
    StartDateTime = $secretStartDate
    EndDateTime = $secretEndDate
}

if (-not $clientSecret) {
    Write-Host "āŒ Failed to create client secret. Exiting."
    exit
}

Write-Host "āœ… Client Secret Created!"

# -------------------------------
# PRINT CREDENTIALS (STORE SECURELY!)
# -------------------------------

$tenantId = (Get-MgOrganization).Id

Write-Host "`nšŸš€ **Application Credentials**"
Write-Host "----------------------------------"
Write-Host "šŸŒ Tenant ID:       $tenantId"
Write-Host "šŸ”‘ Client ID:       $($app.AppId)"
Write-Host "šŸ•µļøā€ā™‚ļø Client Secret:  $($clientSecret.SecretText)"
Write-Host "----------------------------------"

Write-Host "`nāš ļø **IMPORTANT:** Store the Client Secret securely. It will not be retrievable after this session."