ValueOpportunity/Get-FeatureReadiness.ps1

<#
.SYNOPSIS
    Checks prerequisites for non-adopted features.
.DESCRIPTION
    For each feature in sku-feature-map.json, determines readiness state
    (Ready/Blocked/NotLicensed) by checking license status and prerequisite
    adoption. Reads sibling CSVs from the assessment folder. Zero API calls.
.PARAMETER ProjectRoot
    Path to the module root (contains controls/).
.PARAMETER AssessmentFolder
    Path to the assessment output folder (contains sibling CSVs).
#>

[CmdletBinding()]
param(
    [Parameter()]
    [string]$ProjectRoot,

    [Parameter()]
    [string]$AssessmentFolder
)

function Get-FeatureReadiness {
    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter(Mandatory)]
        [PSCustomObject[]]$LicenseUtilization,

        [Parameter(Mandatory)]
        [PSCustomObject[]]$FeatureAdoption,

        [Parameter(Mandatory)]
        $FeatureMap,

        [Parameter()]
        [string]$OutputPath
    )

    $categories = @{}
    foreach ($cat in $FeatureMap.categories) { $categories[$cat.id] = $cat.name }

    $licenseLookup = @{}
    foreach ($lic in $LicenseUtilization) { $licenseLookup[$lic.FeatureId] = $lic }

    $adoptionLookup = @{}
    foreach ($adp in $FeatureAdoption) { $adoptionLookup[$adp.FeatureId] = $adp }

    $featureNameLookup = @{}
    foreach ($f in $FeatureMap.features) { $featureNameLookup[$f.featureId] = $f.name }

    $results = foreach ($feature in $FeatureMap.features) {
        $lic = $licenseLookup[$feature.featureId]
        $blockers = @()

        if (-not $lic -or -not $lic.IsLicensed) {
            $planNames = $feature.requiredServicePlans -join ', '
            [PSCustomObject]@{
                FeatureId      = $feature.featureId
                FeatureName    = $feature.name
                Category       = $categories[$feature.category]
                ReadinessState = 'NotLicensed'
                Blockers       = "Requires $planNames"
                EffortTier     = $feature.effortTier
                LearnUrl       = $feature.learnUrl
            }
            continue
        }

        foreach ($prereqId in $feature.prerequisites) {
            $prereqAdoption = $adoptionLookup[$prereqId]
            if (-not $prereqAdoption -or $prereqAdoption.AdoptionState -notin @('Adopted', 'Partial')) {
                $prereqName = $featureNameLookup[$prereqId]
                if (-not $prereqName) { $prereqName = $prereqId }
                $blockers += "Requires $prereqName"
            }
        }

        $state = if ($blockers.Count -gt 0) { 'Blocked' } else { 'Ready' }

        [PSCustomObject]@{
            FeatureId      = $feature.featureId
            FeatureName    = $feature.name
            Category       = $categories[$feature.category]
            ReadinessState = $state
            Blockers       = ($blockers -join '; ')
            EffortTier     = $feature.effortTier
            LearnUrl       = $feature.learnUrl
        }
    }

    if ($OutputPath) {
        $results | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
        Write-Output "Exported feature readiness ($($results.Count) features) to $OutputPath"
    }
    else {
        Write-Output $results
    }
}

# --- Script entry point (called by orchestrator with -ProjectRoot) ---
if ($ProjectRoot -and $AssessmentFolder) {
    $featureMapPath = Join-Path -Path $ProjectRoot -ChildPath 'controls\sku-feature-map.json'
    if (-not (Test-Path -Path $featureMapPath)) {
        Write-Warning "sku-feature-map.json not found at $featureMapPath"
        return
    }
    $featureMap = Get-Content -Path $featureMapPath -Raw | ConvertFrom-Json

    # Read sibling CSVs
    $licCsvPath = Join-Path -Path $AssessmentFolder -ChildPath '40-License-Utilization.csv'
    $licenseData = @()
    if (Test-Path -Path $licCsvPath) {
        $licenseData = @(Import-Csv -Path $licCsvPath -Encoding UTF8 | ForEach-Object {
            [PSCustomObject]@{
                FeatureId  = $_.FeatureId
                IsLicensed = ($_.IsLicensed -eq 'True')
            }
        })
    }

    $adpCsvPath = Join-Path -Path $AssessmentFolder -ChildPath '41-Feature-Adoption.csv'
    $adoptionData = @()
    if (Test-Path -Path $adpCsvPath) {
        $adoptionData = @(Import-Csv -Path $adpCsvPath -Encoding UTF8)
    }

    Get-FeatureReadiness -LicenseUtilization $licenseData -FeatureAdoption $adoptionData -FeatureMap $featureMap
}