Install-O365Toolkit.ps1

param(
    [string]$Destination,
    [switch]$NoImport,
    [switch]$Force,
    [switch]$SkipDependencies,
    [switch]$InstallDependencies
)

$moduleName = 'O365-Toolkit'
$sourceRoot = Split-Path -Parent $PSCommandPath

# Define required and optional dependencies
$requiredModules = @(
    @{Name = 'ExchangeOnlineManagement'; MinVersion = '3.2.0'; Required = $true},
    @{Name = 'PnP.PowerShell'; MinVersion = '1.12.0'; Required = $true}
)

$optionalModules = @(
    @{Name = 'Microsoft.Graph'; MinVersion = '2.9.0'; Required = $false},
    @{Name = 'Microsoft.Online.SharePoint.PowerShell'; MinVersion = '16.0.22601.12000'; Required = $false}
)

function Get-DefaultModulePath {
    $paths = ($env:PSModulePath -split ';') | Where-Object { $_ -and (Test-Path $_) }

    $preferred = @(
        Join-Path $HOME 'Documents\PowerShell\Modules'), # PowerShell 6+
        (Join-Path $HOME 'Documents\WindowsPowerShell\Modules') # Windows PowerShell
    foreach ($p in $preferred) {
        if (Test-Path $p) { return $p }
    }

    if ($paths) { return $paths[0] }

    $fallback = Join-Path $HOME 'Documents\PowerShell\Modules'
    New-Item -ItemType Directory -Path $fallback -Force | Out-Null
    return $fallback
}

function Test-ModuleInstalled {
    param([string]$ModuleName, [string]$MinVersion)
    
    $module = Get-Module $ModuleName -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1
    if (-not $module) { return $false }
    
    if ($MinVersion) {
        return [version]$module.Version -ge [version]$MinVersion
    }
    return $true
}

function Show-DependencyStatus {
    Write-Host "`n=== Dependency Check ===" -ForegroundColor Cyan
    
    foreach ($module in $requiredModules) {
        $installed = Test-ModuleInstalled -ModuleName $module.Name -MinVersion $module.MinVersion
        $status = if ($installed) { '✓ Installed' } else { '✗ Missing' }
        $color = if ($installed) { 'Green' } else { 'Red' }
        Write-Host " $($module.Name): $status" -ForegroundColor $color
    }
    
    Write-Host "`n Optional Dependencies:" -ForegroundColor Yellow
    foreach ($module in $optionalModules) {
        $installed = Test-ModuleInstalled -ModuleName $module.Name -MinVersion $module.MinVersion
        $status = if ($installed) { '✓ Installed' } else { '✗ Not Installed' }
        $color = if ($installed) { 'Green' } else { 'Yellow' }
        Write-Host " $($module.Name): $status" -ForegroundColor $color
    }
}

function Install-Dependencies {
    $allModules = $requiredModules + $optionalModules
    
    Write-Host "`n=== Installing Dependencies ===" -ForegroundColor Cyan
    
    foreach ($module in $allModules) {
        if (Test-ModuleInstalled -ModuleName $module.Name -MinVersion $module.MinVersion) {
            Write-Host " Skipping $($module.Name) - already installed" -ForegroundColor Gray
            continue
        }
        
        Write-Host " Installing $($module.Name)..." -ForegroundColor Yellow
        try {
            Install-Module -Name $module.Name -Repository PSGallery -AllowClobber -Force -Scope CurrentUser -ErrorAction Stop
            Write-Host " ✓ $($module.Name) installed" -ForegroundColor Green
        }
        catch {
            if ($module.Required) {
                Write-Host " ✗ Failed to install required module $($module.Name): $_" -ForegroundColor Red
                throw
            } else {
                Write-Host " ⚠ Failed to install optional module $($module.Name): $_" -ForegroundColor Yellow
            }
        }
    }
}

# Show dependency status
Show-DependencyStatus

# Handle dependency installation
if ($InstallDependencies) {
    Install-Dependencies
}
elseif (-not $SkipDependencies) {
    Write-Host "`nInstall dependencies now? (Y/n) " -ForegroundColor Yellow -NoNewline
    $response = Read-Host
    if ($response -ne 'n' -and $response -ne 'N') {
        Install-Dependencies
    }
}

# Install the module
$destRoot = if ($Destination) { $Destination } else { Get-DefaultModulePath }
if (-not (Test-Path $destRoot)) {
    New-Item -ItemType Directory -Path $destRoot -Force | Out-Null
}

$targetPath = Join-Path $destRoot $moduleName
if (Test-Path $targetPath) {
    Write-Host "Removing existing module installation at $targetPath..." -ForegroundColor Yellow
    Remove-Item -Recurse -Force $targetPath -ErrorAction SilentlyContinue
    Start-Sleep -Milliseconds 500  # Wait for filesystem to catch up
}

Copy-Item -Path $sourceRoot -Destination $targetPath -Recurse -Force -Exclude '.git','*.Tests.ps1','Tests'

if (-not $NoImport) {
    Import-Module (Join-Path $targetPath "$moduleName.psd1") -Force
}

Write-Host "`nInstalled $moduleName to $targetPath" -ForegroundColor Green
if (-not $NoImport) {
    Write-Host "Module imported. Try Get-Command -Module $moduleName to explore." -ForegroundColor Green
}
else {
    Write-Host "Import manually with: Import-Module '$targetPath\$moduleName.psd1'" -ForegroundColor Yellow
}