tool/Automation/functions/Export-OpportunityResults.ps1

function Export-OpportunityResults {
    <#
    .SYNOPSIS
        Export scored results to Excel, CSV, JSON, and HTML formats.

    .DESCRIPTION
        Reads scoring-results.json and produces:
        - opportunity-report.xlsx (template-injected workbook with charts, pivots, KPIs)
        - opportunity-report.csv
        - opportunity-report.json (flat export)
        - opportunity-report.html (interactive report)

        Excel generation uses ImportExcel module with template injection.
        If the template is missing or injection fails, Excel is skipped with a warning.

    .PARAMETER ScoringPath
        Path to scoring-results.json from the score stage.

    .PARAMETER OutputPath
        Path to output/ directory where reports will be written.

    .PARAMETER ManifestPath
        Path to email-manifest.json (used for email count in Excel template).

    .OUTPUTS
        PSCustomObject with files_created.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$ScoringPath,

        [Parameter(Mandatory)]
        [string]$OutputPath,

        [Parameter()]
        [string]$ManifestPath
    )

    # Load scoring results
    $scoring = Get-Content $ScoringPath -Raw | ConvertFrom-Json

    # Ensure output directory
    if (-not (Test-Path $OutputPath -PathType Container)) {
        New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
    }

    # --- Flatten results for export ---
    $flatResults = foreach ($result in $scoring.results) {
        [ordered]@{
            Band                   = $result.band
            Urgency                = $result.urgency
            'Final Score'          = $result.final_score
            'Composite Score'      = $result.composite_score
            'Recency Penalty'      = $result.recency_penalty_applied
            'Contact Name'         = $result.contact_name
            'Contact Email'        = $result.contact_email
            Organisation           = $result.organisation
            Role                   = $result.role
            'Current Title'        = $result.current_title
            'Current Organisation' = $result.current_organisation
            'Still in Role'        = $result.still_in_role
            'Telematics Activity'  = $result.telematics_activity
            Confidence             = $result.confidence
            'Email Date'           = $result.email_date
            Category               = ($result.category -join ', ')
            'Strategic Fit'        = $result.sub_scores.strategic_fit.raw
            Seniority              = $result.sub_scores.seniority.raw
            'Engagement Warmth'    = $result.sub_scores.engagement_warmth.raw
            'Market Activity'      = $result.sub_scores.market_activity.raw
            'Conversation Stage'   = $result.sub_scores.conversation_stage.raw
            Recency                = $result.sub_scores.recency.raw
            'Research Confidence'  = $result.sub_scores.research_confidence.raw
            'Recommended Action'   = $result.recommended_action
            'Action Rationale'     = $result.action_rationale
            'Source URLs'          = ($result.source_urls -join '; ')
            'Source File'          = $result.file_path
        }
    }

    $flatResults = @($flatResults)
    $filesCreated = @()

    # --- CSV Export ---
    $csvPath = Join-Path $OutputPath 'opportunity-report.csv'
    $flatResults | ForEach-Object { [PSCustomObject]$_ } |
    Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
    $filesCreated += $csvPath
    Write-Host " CSV: $csvPath" -ForegroundColor Gray

    # --- JSON Export (flat) ---
    $jsonPath = Join-Path $OutputPath 'opportunity-report.json'
    $jsonExport = [ordered]@{
        exported_at = (Get-Date).ToString('o')
        profile     = $scoring.metadata.profile_used
        total       = $flatResults.Count
        results     = $flatResults
    }
    $jsonExport | ConvertTo-Json -Depth 5 | Set-Content -Path $jsonPath -Encoding UTF8
    $filesCreated += $jsonPath
    Write-Host " JSON: $jsonPath" -ForegroundColor Gray

    # --- Excel Export via Template Injection ---
    $xlsxPath = Join-Path $OutputPath 'opportunity-report.xlsx'

    try {
        # Resolve profile for config injection
        $profileName = $scoring.metadata.profile_used
        if (-not $profileName) { $profileName = 'Default' }
        $scriptDir = Split-Path $MyInvocation.MyCommand.ScriptBlock.File -Parent
        $moduleRoot = $scriptDir | Split-Path -Parent | Split-Path -Parent | Split-Path -Parent
        $profilePath = Join-Path $moduleRoot 'profiles' "$profileName.json"
        $profileData = Get-Content $profilePath -Raw | ConvertFrom-Json

        # Determine email count from manifest
        $emailCount = 0
        if ($ManifestPath -and (Test-Path $ManifestPath)) {
            $manifest = Get-Content $ManifestPath -Raw | ConvertFrom-Json
            $emailCount = $manifest.emails.Count
        }

        # Get version from module manifest
        $psd1Path = Join-Path $moduleRoot 'LeadForge.psd1'
        $moduleVersion = '1.3.0'
        if (Test-Path $psd1Path) {
            $psd1 = Import-PowerShellDataFile $psd1Path
            $moduleVersion = $psd1.ModuleVersion
        }

        Export-ExcelFromTemplate `
            -FlatResults $flatResults `
            -OutputFilePath $xlsxPath `
            -Profile $profileData `
            -EmailCount $emailCount `
            -Version $moduleVersion

        $filesCreated += $xlsxPath
        Write-Host " Excel: $xlsxPath" -ForegroundColor Gray
    }
    catch {
        Write-Warning "Excel export failed: $($_.Exception.Message)"
    }

    # --- HTML Report ---
    try {
        $htmlMeta = @{
            profile     = $scoring.metadata.profile_used
            exported_at = (Get-Date).ToString('o')
        }
        $htmlFile = Export-HtmlReport -Results $flatResults -Metadata $htmlMeta -OutputPath $OutputPath
        $filesCreated += $htmlFile
        Write-Host " HTML: $htmlFile" -ForegroundColor Gray
    }
    catch {
        Write-Warning "HTML report failed: $($_.Exception.Message)"
    }

    [PSCustomObject]@{
        files_created = $filesCreated
        total_results = $flatResults.Count
    }
}