functions/Install-HydrationEpac.ps1

<#
.SYNOPSIS
    This function deploys Enterprise Policy as Code locally, and configures the repo to be uploaded to the platform of your choice.
.DESCRIPTION
    The Install-HydrationEpac function deploys the Enterprise Policy as Code. It takes several optional parameters: DefinitionsRootFolder, StarterKit, AnswerFile, Output, StopPoint, UseUtc, Interactive, and SkipTests.
.PARAMETER TenantIntermediateRoot
    The name of the Tenant Intermediate Root. This parameter is mandatory.
.PARAMETER DefinitionsRootFolder
    The path to the Definitions directory. Defaults to "./Definitions".
.PARAMETER StarterKit
    The path to the StarterKit directory. Defaults to "./StarterKit".
.PARAMETER Output
    The path to the Output directory. Defaults to "./Output".
.PARAMETER AnswerFile
    The path to the Answer file. This parameter is optional and does not have a default value.
.PARAMETER UseUtc
    Switch to use UTC time.
.PARAMETER Interactive
    Switch to enable interactive mode.
.PARAMETER SkipTests
    Switch to skip preliminary tests.
.EXAMPLE
    Install-HydrationEpac -TenantIntermediateRoot "/path/to/root"
    This example deploys the Enterprise Policy as Code using the specified Tenant Intermediate Root and default directories, which is appropriate if being run from the root of the new repo.
.LINK
    https://aka.ms/epac
    https://github.com/Azure/enterprise-azure-policy-as-code/tree/main/Docs/start-hydration-kit.md
#>

function Install-HydrationEpac {
    [CmdletBinding()]
    [Alias("Build-EpacRepo", "ber")]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "The path to the Tenant Intermediate Root. This parameter is mandatory.")]
        [string]
        $TenantIntermediateRoot,
        [Parameter(Mandatory = $false, HelpMessage = "The path to the Definitions directory. Defaults to './Definitions'.")]
        [string]
        $DefinitionsRootFolder = "./Definitions",
        # [Parameter(Mandatory = $false, HelpMessage = "The path to the StarterKit directory. Defaults to './StarterKit'.")]
        # [string]
        # $StarterKit = "./StarterKit",
        [Parameter(Mandatory = $false, HelpMessage = "The path to the Output directory. Defaults to './Output'.")]
        [string]
        $Output = "./Output",
        [Parameter(Mandatory = $false, HelpMessage = "The path to the Answer file. This parameter is optional and does not have a default value.")]
        [string]
        $AnswerFile,
        [Parameter(Mandatory = $false, HelpMessage = "Switch to use UTC time.")]
        [switch]
        $UseUtc,
        [Parameter(Mandatory = $false, HelpMessage = "Switch to enable interactive mode.")]
        [switch]
        $Interactive,
        [Parameter(Mandatory = $false, HelpMessage = "Switch to skip preliminary tests.")]
        [switch]
        $SkipTests

    )
    # Define UI Width for display automation
    if ($host.UI.RawUI.WindowSize.Width -lt 80 -or $host.UI.RawUI.WindowSize.Width -eq "" -or $null -eq $host.UI.RawUI.WindowSize.Width) {
        $TerminalWidth = 80
    }
    else {
        $TerminalWidth = $host.UI.RawUI.WindowSize.Width
    }
    $stageBlocks = Get-HydrationMessageBlock -TerminalWidth $TerminalWidth
    $epacDevName = "epac-dev"
    Clear-Host
    $sleepTime = 10
    # Define Verbosity
    $InformationPreference = "Continue"
    if ($TenantIntermediateRoot -eq $(Get-AzContext).Tenant.Id) {
        Write-Error "The Tenant Intermediate Root specified is the same as the current connected Tenant ID. This is not recommended as it can lead to a less secure outcome, and for this reason this script does not support the configuration. Please choose an intermediate root that is not your Tenant Root."
    }
    if(!(Test-Path $DefinitionsRootFolder)){
        $null = New-Item -Path $DefinitionsRootFolder -ItemType Directory -Force
    }
    $DefinitionsRootFolder = (Resolve-Path $DefinitionsRootFolder).Path
    $repoRootPath = Split-Path $DefinitionsRootFolder
    Set-Location $repoRootPath
    if(!(Test-Path $DefinitionsRootFolder)){
        $null = New-Item -Path $DefinitionsRootFolder -ItemType Directory -Force
    }
    if(!(Test-Path $Output)){
        $null = New-Item -Path $Output -ItemType Directory -Force
    }
    $Output = (Resolve-Path $Output).Path
    $exportedDefinitionsPath = @{
        root = Join-Path $Output "Export"
        definitions = Join-Path $Output "Export" "Definitions"
        policyAssignments = Join-Path $Output "Export" "Definitions" "policyAssignments"
        policyDefinitions = Join-Path $Output "Export" "Definitions" "policyDefinitions"
        policySetDefinitions = Join-Path $Output "Export" "Definitions" "policySetDefinitions"
        policyExemptions = Join-Path $Output "Export" "Definitions" "policyExemptions"
        exportPolicyToEpac = Join-Path $Output "Export" "policyAssignments"
        starterKit = Join-Path $repoRootPath "StarterKit"
    }
    # Move to repo root as EPAC generally prefers to be run from this location
    $logDirectory = Join-Path $Output "Logs"
    $logFilePath = Join-Path $logDirectory "Install-HydrationEpac.log"
    # $questionsFilePath = Join-Path $StarterKit "HydrationKit" "questions.jsonc"
    if(!(Test-Path $logDirectory)){
        $null = New-Item -Path $logDirectory -ItemType Directory -Force
    }
    # Import, fail to import, or create the answer file
    if ($AnswerFile) {
        if (!(Test-Path $AnswerFile)) {
            Write-Error "Answer file not found at $AnswerFile, exiting..."
            return
        }
        $allInterviewAnswers = Get-Content $AnswerFile `
            | ConvertFrom-Json -Depth 10 -AsHashtable
        $answerFilePath = Resolve-Path $AnswerFile
    }
    else {
        $answerFilePath = Join-Path $Output `
            "HydrationAnswer" `
            "AnswerFile.json"
        if (!(Test-Path $(Split-Path $answerFilePath))) {
            $null = New-Item -Path $(Split-Path $answerFilePath) -ItemType Directory -Force
        }
        else {
            if($Interactive){
                Write-Warning "A file already exists at $answerFilePath, and will be overwritten unless you use Ctrl+C to exit..."
                Read-Host "Press Enter to continue..."
            }
            Write-HydrationLogFile -EntryType logEntryDataAsPresented `
                -EntryData "Overwriting Answer File at $answerFilePath" `
                -LogFilePath $logFilePath `
                -UseUtc:$UseUtc
        }
        "" | Set-Content $answerFilePath -Force
    }


    # Crete an ordered hashtable to hold log entries until the directories are tested
    $endSummary = [PSCustomObject]@{
        preliminaryTestResults  = [ordered]@{}
        gatherData              = [ordered]@{}
        generateAnswerFile      = [ordered]@{}
        importAnswerFile        = [ordered]@{}
        populateRepoDefinitions = [ordered]@{}
        createRepo              = [ordered]@{}
        testRepo                = [ordered]@{}
        testAndPlan             = [ordered]@{}
        buildRepo               = [ordered]@{}
        deployRepo              = [ordered]@{}
        deployPipelines         = [ordered]@{}
        deployPolicyAssignments = [ordered]@{}
        deployPolicyDefinitions = [ordered]@{}
        deployPolicyRoles       = [ordered]@{}
    }
    $interviewQuestionSets = [ordered]@{
        initial                               = $true
        optionalCreatePrimaryIntermediateRoot = $false
        optionalCreateMainCaf3Hierarchy       = $false
        tenantList                            = $false # Future state
        pacSelector                           = $true
        updatesByPacSelector                  = $true
        policyDecisionsByPacSelector          = $true
        pipeline                              = $true
    }
    # $roleMessages = @{
    # "PassedEpacAllDeploy" = "- The script will be unable to assist with building the new management groups for EPAC to test with during development. However, RBAC Authorization tests passed, and you have the necessary permissions to deploy the EPAC solution to existing management groups. It is recommended that you ensure that you already have your epac development hierarchy in place prior to continuing so that these initial test deployments can be run."
    # "PassedEpacPolicyDeploy" = "- The script will be unable to deploy any roles to support policies that are deployed by EPAC. This can result in an unsupported state, so no deployments step will be offered."
    # "PassedEpacRoleDeploy" = "- The script will be unable to deploy any policies used by the roles that will be deployed by EPAC. This can result in an unsupported state, so no deployment step will be offered."
    # "PassedEpacPlan" = "- The script will be unable to deploy any aspect of the EPAC solution to Azure. Only a plan step will be offered."
    # "Failed" = "- The script will be unable to plan a deployment to support the EPAC solution. No plan step will be offered, and there will be no attempt to gather data from Azure programatically to simplify this process."
    # }
    $limitation = [ordered]@{
        Write  = @{
            Status              = $false
            Message             = "The script will be unable to create the epac testing environment for testing as part of this process. Consider manually creating these management groups prior to continuing..." 
            optionalCaf3Message = "This script will be unable to create the requisite management groups for the new caf3 management group hierarchy due to limitations of the account used for the current connection to Azure, these questions will be skipped. Consider creating the new Tenant Intermediate Root Group and restarting the process"
            optionalTirMessage  = "This script will be unable to create the recommended management groups for the new caf3 management group hierarchy due to limitations of the account used for the current connection to Azure, these questions will be skipped. STRONGLY consider creating the new Tenant Intermediate Root Group and restarting the process."
        }
        Policy = @{
            Status  = $false
            Message = "The script will be unable to deploy policy, and will not continue beyond the plan phase." 
        }
        Role   = @{
            Status  = $false
            Message = "The script will be unable to deploy roles that are needed to support policy deployment, and will not continue beyond the plan phase." 
        }
        Plan   = @{
            Status  = $false
            Message = "The script is unable to read the environment to generate a plan, so deployment of Azure Policy will not be tested against the EPAC development environment specified."
        }
        Gather = @{
            Status  = $false
            Message = "The script will be unable to gather data from Azure programatically to simplify this process. No insights from Azure can be gained to assist in guiding you through this process... Stopping now and rerunning the tests after connecting to Azure with an account that has more comprehensive rights, at least Read, to Azure, is STRONGLY recommended." 
        }
        Git    = @{
            Status  = $false
            Message = "The script will be unable to programatically download the StarterKit from GitHub. Please ensure that you have an updated copy of StarterKit in the same directory as the Definitions folder, based on the choices made in this script." 
        }
    }

    ##################### INSERT INITIAL BLOCK HERE
    
    # $stageBlocks = Get-HydrationMessageBlock
    # foreach ($key in $stageBlocks2.keys) {
    # $stageBlocks2.$key.TerminalWidth = $TerminalWidth
    # $stageBlocks.add($key, $stageBlocks2.$key)
    # }
    # Remove-Variable stageBlocks2 -ErrorAction SilentlyContinue
    # $stageBlocks = [ordered]@{
    # }
    Clear-Host
    ################################################################################
    ################################################################################
    # Initiate UI: Header
    $summary = [ordered]@{}
    $uiStart = $stageBlocks.uiStart
    New-HydrationSeparatorBlock @uiStart
    Write-HydrationLogFile -EntryType newStage `
        -EntryData $stageBlocks.uiStart.DisplayText `
        -LogFilePath $logFilePath `
        -UseUtc:$UseUtc `
        -Silent

    # Initiate UI: Body
    # TODO Add a welcome message here that is more informative than the current placeholder.
    Write-Host "Welcome to the Enterprise Policy as Code (EPAC) Hydration Kit. This script is intended to help guide you through the EPAC Deployment process." -ForegroundColor Yellow
    Write-Host "Please report any issues to the EPAC team." -ForegroundColor Yellow
    # Initiate UI: Footer
    New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime
    Clear-Host

    ################################################################################
    ################################################################################
    # Preliminary Tests: Path Header
    $summary = [ordered]@{}
    $runPreliminaryTests = $stageBlocks.runPreliminaryTests
    New-HydrationSeparatorBlock @runPreliminaryTests
    Write-HydrationLogFile -EntryType newStage `
        -EntryData $stageBlocks.runPreliminaryTests.DisplayText `
        -LogFilePath $logFilePath `
        -UseUtc:$UseUtc `
        -Silent
    ################################################################################
    # Preliminary Tests: Path Body
    Write-Host "Beginning path tests to help ensure that the script can run successfully..." -ForegroundColor Yellow
    # Test for and create directories if they do not exist, this allows realtime logging to file to begin

    if ($SkipTests) {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Skipping tests..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Magenta
    }
    else {
        # foreach ($path in $pathsToTest) {
        # $pathTest = Test-HydrationPath -LocalPath $path `
        # -UseUtc:$UseUtc `
        # -LogFilePath $logFilePath `
        # -Silent
        # if ($pathTest -eq "Failed") {
        # Write-Error "The path $path could not be created. Please choose a location to work in that you have write access to and restart the process."
        # $summary.Add($path, "Failed")
        # }
        # else {
        # $summary.Add($path, "Passed")
        # }
        # }
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Summary of $($stageblocks.runPreliminaryTests.DisplayText)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        foreach ($entry in $summary.keys) {
            Write-HydrationLogFile -EntryType testResult -EntryData "$entry -- $($summary.$entry)" -UseUtc:$UseUtc -LogFilePath $logFilePath -Silent
            Start-Sleep -Seconds $sleepTime
        }
        # Begin Azure Network Connection Tests
        Write-Host "Beginning connectivity tests to help ensure that the script can run successfully..." -ForegroundColor Yellow
        $connectionTestUrlList = [ordered]@{
            internetConnection  = "13.107.42.14" # Used in Microsoft Automated Testing (per CoPilot)
            githubConnection    = "www.github.com"
            azureManagement     = (Get-AzContext).Environment.ResourceManagerUrl | Select-String -Pattern "https?://([^/]+)/?" | ForEach-Object {
                $_.Matches[0].Groups[1].Value
            }
            azureAuthentication = (Get-AzContext).Environment.ActiveDirectoryAuthority | Select-String -Pattern "https?://([^/]+)/?" | ForEach-Object {
                $_.Matches[0].Groups[1].Value
            }
        }
        foreach ($url in $connectionTestUrlList.Keys) {
            $connectionTest = Test-HydrationConnection -FullyQualifiedDomainName $connectionTestUrlList.$url -UseUtc:$UseUtc -LogFilePath $logFilePath -Silent
            if ($connectionTest -eq "Failed") {
                # Write-Error "The test for $url failed when tested with the value $($connectionTestUrlList.$url). Please ensure that you have an active internet connection and that the Azure services are available. This will not prevent continuing with the process, but it will prevent use of much of the accelerator, as well as gathering of data to provide guidance in this process, and is not recommended."
                $summary.Add($url, "Failed")
            }
            else {
                $summary.Add($url, "Passed")
            }
            Write-HydrationLogFile -EntryType testResult -EntryData "$url -- $($summary.$url)" -UseUtc:$UseUtc -LogFilePath $logFilePath -Silent
        }
        # Begin Git Installation Test
        Write-Host "Beginning git tests to help ensure that the script can run successfully..." -ForegroundColor Yellow
        try {
            if (($(git --help))) {
                $summary.add("gitInstall", "Passed")
            }
        }
        catch {
            $summary.add("gitInstall", "Failed")
            if(!((Get-ChildItem ./StarterKit/* -Recurse).count -gt 0)){
                Write-Host "Download the repo at https://github.com/Azure/enterprise-azure-policy-as-code and extract it to the root directory to continue. The StarterKit is required for pipeline deployment..." -ForegroundColor Red
                Write-Error "Without either git to download the repo, or a Module and [repoRootDirectory]/StarterKit folder, this installer will not work as intended. Please choose one of the two supported paths forward, and run the installer again."
                return
            }
        }
        
        Write-Host "Reviewing Returns..." -ForegroundColor Yellow
        
        # Process failed tests for warning messages and script limitations calculations
        $failedTests = @{}
        foreach ($key in $summary.keys) {
            if ($summary.$key -like "Failed*") {
                $failedTests.Add($key, $summary.$key)
            }
        }
        
        # if ($failedTests.keys.count -gt 0 -or (!($($summary.RBACAuthorization -eq "PassedHydrationDeploy")))) {
        if ($failedTests.keys.count -gt 0) {
            Write-Host "The following items should be considered before continuing:" -ForegroundColor Red
            foreach ($key in $failedTests.keys) {
                switch ($key) {
                    "githubConnection" {
                        Write-Host " - The test for a connection to GitHub failed. You will need to ensure that the StarterKit folder has been downloaded to the same directory that your Definitions folder is now in, based on the choices made in this script.`
                        `n - This is not a blocker if you have a fresh copy of the StarterKit in the same directory as the Definitions folder, and you already have access to the module. However, this script requires the presence of that folder in the repo to continue, either through automated or manual means.`
                        `n - Download Location: https://github.com/Azure/enterprise-azure-policy-as-code/tree/main/StarterKit"
 -ForegroundColor Yellow
                    }
                    "azureManagement" {
                        Write-Host " - The test for the management connection to Azure failed. The script will be unable to plan a deployment to support the EPAC solution. No plan step will be offered, and there will be no attempt to gather data from Azure programatically to simplify this process." -ForegroundColor Red
                        $limitation.azureManagement.Status = $true
                    }
                    "azureAuthentication" {
                        Write-Host " - The test for the authentication connection to Azure failed. The script will be unable to plan a deployment to support the EPAC solution. No plan step will be offered, and there will be no attempt to gather data from Azure programatically to simplify this process."  -ForegroundColor Red
                        $limitation.azureAuthentication.Status = $true
                    }
                    "gitInstall" {
                        Write-Host " - The test for git software has failed. You will need to ensure that the StarterKit folder has been manually downloaded to the same directory that your Definitions folder is now in, based on the choices made in this script.`
                        `n - This is not a blocker if you have a fresh copy of the StarterKit in the same directory as the Definitions folder, and you already have access to the module. However, this script requires the presence of that folder in the repo to continue, either through automated or manual means.`
                        `n - Download Location: https://github.com/Azure/enterprise-azure-policy-as-code/tree/main/StarterKit"
 -ForegroundColor Yellow
                        $limitation.git.Status = $true
                    }
                }
            }
        }
        else {
            Write-Host "All tests indicate that the connection is in an optimal state for the EPAC installation process. Additional data will be gathered using these connections, and errors after this point will generally indicate a unique condition such as an inheritance block/override for RBAC authority." -ForegroundColor Green
        }
        



        ################################################################################
        # Preliminary Tests: Footer

        # Summary separator block
        $displayPreliminaryTests = $stageBlocks.displayPreliminaryTests
        New-HydrationSeparatorBlock @displayPreliminaryTests
        Write-HydrationLogFile -EntryType newStage -EntryData $stageBlocks.displayPreliminaryTests.DisplayText -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent

        # Display Summary
        $testSummarySeparator = "-"
        foreach ($hashkey in $summary.keys) {
            $hashString = $( -join ($hashKey, " ", ($testSummarySeparator * ($TerminalWidth - ($hashKey.Length + $($summary.$hashKey).Length + 2))), " ", $($summary.$hashKey)))
            if ($summary.$hashkey -like "Failed*") {
                Write-Host $hashString -ForegroundColor Red
            }
            else {
                Write-Host $hashString -ForegroundColor Green
            }
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Summary: $hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        }
        Write-Host "`n`n"

        # Pause for review based on interactive message from input
        New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime
    }
    ################################################################################
    ################################################################################
    # Begin Data Gather Process to Support EPAC Deployment
    $summary = [ordered]@{}
    $gatherData = $stageBlocks.gatherData
    New-HydrationSeparatorBlock @gatherData
    Write-HydrationLogFile -EntryType newStage -EntryData $stageBlocks.gatherData.DisplayText -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent

    Write-Host "Beginning data gathering process..." -ForegroundColor Yellow

    # Gather Data
    $gatherData = [ordered]@{}
    $environmentEntry = [ordered]@{
        pacSelector                = ""
        intermediateRootGroupName  = $TenantIntermediateRoot
        tenantId                   = $(Get-AzContext).Tenant.Id
        cloud                      = $(Get-AzContext).Environment.Name
        keepDfcSecurityAssignments = $false
        caf3Status                 = "Untested"
        intermediateRootStatus     = "Untested"
    }
    # Current Tenant Information
    try {
        $gatherData.Add('currentTenantPacSelector', $(Get-DeepCloneAsOrderedHashtable -InputObject $environmentEntry))
        $gatherData.currentTenantPacSelector.pacSelector = "tenant01" # Set Default for primary tenant, primary root (that will be cloned to epac-dev environment)
    }
    catch {
        Write-Error "Cannot find the EPAC helper command `'Get-DeepCloneAsOrderedHashtable`', please ensure that the EPAC module or is installed and available, or that the scripts directory is available and the helpers have been dot sourced for use."
        return
    }
    try { 
        $psdList = Get-AzPolicySetDefinition -ManagementGroupName $(Get-AzContext).Tenant.Id
    }
    catch {
        Write-Error "Failed to gather Azure Policy Set Definition List, please ensure that you have a connection to Azure and try again."
        return
    }
    $gatherData.Add('policySetDefinitions', $psdList)
    Remove-Variable psdList -ErrorAction SilentlyContinue
    try { 
        $pdList = Get-AzPolicyDefinition -ManagementGroupName $(Get-AzContext).Tenant.Id
    }
    catch {
        Write-Error "Failed to gather Azure Policy Set Definition List, please ensure that you have a connection to Azure and try again."
        return
    }
    $gatherData.Add('policyDefinitions', $pdList)
    Remove-Variable pdList -ErrorAction SilentlyContinue
    try {
        $locationList = (Get-AzLocation -ErrorAction SilentlyContinue).location
        if ($locationList.count -gt 0) {
            $gatherData.Add('locationList', @($LocationList) -join ", ")
        }
    }
    catch {
        Write-Error "Failed to gather Azure Location List, please ensure that you have a connection to Azure and try again."
        return
    }
    try {
        $tenantIntermediateRootTestResult = Get-AzManagementGroupRestMethod -GroupID $TenantIntermediateRoot
    }
    catch {
        Write-Warning "Error returned retrieving the Tenant Intermediate Root. This generally means that it has not been created, and the interview process will continue with the assumption that it needs to be created."
    }
    if (!($tenantIntermediateRootTestResult.Id)) {
        $gatherData.currentTenantPacSelector.intermediateRootStatus = $environmentEntry.intermediateRootStatus = "Available"
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "The Tenant Intermediate Root Management Group does not exist, and will need to be created to be used." -LogFilePath $logFilePath -UseUtc:$UseUtc -silent 
        $interviewQuestionSets.optionalCreatePrimaryIntermediateRoot = $true
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Create Intermediate Root: `"$TenantIntermediateRoot`" does not exist, adding discussion items..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    }
    else {
        $gatherData.currentTenantPacSelector.intermediateRootStatus = $environmentEntry.intermediateRootStatus = "Passed"
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "The TenantIntermediateRoot Management Group `"$TenantIntermediateRoot`" is confirmed." -LogFilePath $logFilePath -UseUtc:$UseUtc -silent 
        $interviewQuestionSets.optionalCreatePrimaryIntermediateRoot = $false
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Create Intermediate Root Test: `"$TenantIntermediateRoot`" exists , no deployment is needed..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
    }

    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Data Gathered: $($gatherData | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
    Write-Host "`n"
    $endSummary.gatherData = $summary
    New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime
    # }
    ################################################################################
    ################################################################################
    # Download Repo Contents
    Get-HydrationEpacRepo -RepoRoot $RepoRoot
    try{
        Copy-Item -Path $repoRoot "temp" "StarterKit" -Destination $exportedDefinitionsPath.starterKit -Recurse -Force
    }
    catch{
        Write-Warning "Failed to copy StarterKit directory: $($_.Exception.Message)"
    }
    # # $stageBlocks2 = Get-Content $(Join-Path $StarterKit 'HydrationKit' 'blockDefinitions.jsonc') | ConvertFrom-Json -Depth 5 -AsHashtable

    if ($answers.useModuleorScript -eq "LocalScript") {
        $scriptsSourcePath = Join-Path -Path $repoRootPath -ChildPath "temp" "Scripts"
        $scriptDestinationPath = Join-Path -Path $repoRootPath -ChildPath "Scripts"
        Copy-Item $scriptsSourcePath $scriptDestinationPath -Recurse -Force
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Copied Scripts directory to repo for use in ongoing operations..." -LogFilePath $logFilePath -UseUtc:$UseUtc
    }
    ################################################################################
    ################################################################################
    # Run Interview Process
    if ($AnswerFile) {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Answer File Provided: $AnswerFile" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        try {
            $allInterviewAnswers = Get-Content $AnswerFile | ConvertFrom-Json -Depth 10 -AsHashtable
        }
        catch {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $Error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to import the answer file, please review the error message and rerun the process." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
        }
    }
    else {
        ################################################################################
        # Detection logic for this can be added later if AI doesn't become the primary avenue.
        # $interviewquestionSets.createIntermediateRootHierarchy = $true
        $interviewQuestionSets.optionalCreatePrimaryIntermediateRoot = $true
        $interviewQuestionSets.optionalCreateMainCaf3Hierarchy = $true
        $interviewQuestionSets.optionalRequireCaf3HierarchyRename = $true
        ################################################################################
        ################################################################################
        # Gather Deployment Decisions for/from Answer File

        # Run Interview Process
        Clear-Host
        $stageBlock = $stageBlocks.generateAnswerFile
        $allInterviewAnswers = [ordered]@{}
        New-HydrationSeparatorBlock @stageBlock
        Write-HydrationLogFile -EntryType newStage -EntryData $stageBlock.DisplayText  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
    
        ################################################################################
        # Main Tenant Loops
        ############
        # Confirm Tenant
        $loopId = "initial"
        Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        if ($interviewQuestionSets.$loopId) {
            $loopNotes = @(
                "Current Tenant ID: $((Get-AzContext).tenant.Id)"
            )
            try {
                $interview = New-HydrationAnswerSet -LoopId $loopId -Notes $loopNotes -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
            }
            catch {
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
                Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
                return
            }
            Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Remove-Variable loopId -ErrorAction SilentlyContinue
            Remove-Variable loopNotes -ErrorAction SilentlyContinue
            Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
            foreach ($intKey in $interview.keys) {
                $allInterviewAnswers.Add($intKey, $interview.$intKey)
                $testSummarySeparator = "-"
                $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
            }
            # Process Responses
            if ($interview.initialTenantId -eq "Yes") {
                $allInterviewAnswers.initialTenantId = (Get-AzContext).tenant.id
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nNo Tenant ID was provided, using the current Tenant ID...`n" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
            }
            else {
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nDiffering Tenant ID provided, exiting to use the provided Tenant ID...`n" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
                Write-Error "Reconnect to the appropriate Tenant ID using `'Connect-AzAccount -TenantId [YourTenantId]`', and then rerun the process."
                return
            }
            if ($interview.pacOwnerId -eq "" -or $null -eq $interview.pacOwnerId) {
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nNo Owner ID was provided, generating a new GUID for the Owner ID...`n" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
                $interview.pacOwnerId = $allInterviewAnswers.pacOwnerId = (New-Guid).Guid
                $testSummarySeparator = "-"
                $ikey = "PacOwnerId Generated"
                $hashString = $( -join ($ikey, " ", ($testSummarySeparator * ($TerminalWidth - ($ikey.Length + $($interview.pacOwnerId).Length + 2))), " ", $($interview.pacOwnerId)))
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
            }
            New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime
            $allInterviewAnswers.initialTenantCloud = (Get-AzContext).environment.name
            $allInterviewAnswers.initialTenantIntermediateRoot = $TenantIntermediateRoot
        }

        $loopId = "optionalCreatePrimaryIntermediateRoot"
        Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        if ($environmentEntry.intermediateRootStatus -eq "Available" -and $interviewQuestionSets.$loopId) {
            $loopNotes = @(
                "$TenantIntermediateRoot Name Status: $($environmentEntry.intermediateRootStatus)"
            )
            try {
                $interview = New-HydrationAnswerSet -LoopId $loopId -Notes $loopNotes -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
            }
            catch {
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
                Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
                return
            }
            Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Remove-Variable loopId -ErrorAction SilentlyContinue
            Remove-Variable loopNotes -ErrorAction SilentlyContinue
            Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
            foreach ($intKey in $interview.keys) {
                $allInterviewAnswers.Add($intKey, $interview.$intKey)
                $testSummarySeparator = "-"
                $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green

            }
            New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime
        }
                ############
        # corePacSelectors Loop
        $loopId = "corePacSelectors"
        Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        if (!($endSummary.gatherData.locationList -eq "" -or $null -eq $endSummary.gatherData.locationList)) {
            $loopNotes = @("Location List: $($endSummary.gatherData.locationList)")
        }
        else {
            # $loopNotes = @("Location List: Rbac Test Failed, no location list gathered.")
        }
        try {
            $interview = New-HydrationAnswerSet -LoopId $loopId -Notes $loopNotes -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
        }
        catch {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
            return
        }
        Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
        foreach ($intKey in $interview.keys) {
            $allInterviewAnswers.Add($intKey, $interview.$intKey)
            $testSummarySeparator = "-"
            $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green

        }
        Remove-Variable loopId -ErrorAction SilentlyContinue
        Remove-Variable loopNotes -ErrorAction SilentlyContinue
        if ($interview.mainTenantMainPacSelectorName -eq "" -or $null -eq $interview.mainTenantMainPacSelectorName -or -not $interview.mainTenantMainPacSelectorName) {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "No pacSelectorName was provided, using 'tenant01'..." -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nNo pacSelectorName was provided, setting default value...`n" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
            $interview.mainTenantMainPacSelectorName = $allInterviewAnswers.mainTenantMainPacSelectorName = "tenant01"
            $testSummarySeparator = "-"
            $ikey = "pacSelectorName"
            $hashString = $( -join ($ikey, " ", ($testSummarySeparator * ($TerminalWidth - ($ikey.Length + $($interview.mainTenantMainPacSelectorName).Length + 2))), " ", $($interview.mainTenantMainPacSelectorName)))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
        }
        if ($interview.epacParent -eq "" -or $null -eq $interview.epacParent -or -not $interview.epacParent) {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "No Parent for EPAC was provided, using Tenant Root for the Parent..." -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nNo epacParent was provided, setting default value...`n" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
            $interview.epacParent = $allInterviewAnswers.epacParent = $gatherData.currentTenantPacSelector.tenantId
            $testSummarySeparator = "-"
            $ikey = "epacParent"
            $hashString = $( -join ($ikey, " ", ($testSummarySeparator * ($TerminalWidth - ($ikey.Length + $($interview.epacParent).Length + 2))), " ", $($interview.epacParent)))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
        }
        New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime    

        ############
        # epacModifier Loop
        $loopId = "epacModifier"
        Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent

        try {
            $interview = New-HydrationAnswerSet -LoopId $loopId -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
        }
        catch {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
            return
        }
        Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
        foreach ($intKey in $interview.keys) {
            $allInterviewAnswers.Add($intKey, $interview.$intKey)
            $testSummarySeparator = "-"
            $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
        }
        $epacDevRoot = $( -join ($interview.epacPrefix, $TenantIntermediateRoot, $interview.epacSuffix))
        if ($epacDevRoot -eq $TenantIntermediateRoot) {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nEPAC Development Root $epacDevRoot is equal to the specified Tenant Intermediate Root group, $TenantIntermediateRootGroup. This will result in a name collision. Please choose a prefix and/or suffx when you run this process again." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
            New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime
            return
        }
        else {
            $testSummarySeparator = "-"
            $ival = $( -join ($interview.epacPrefix, $TenantIntermediateRoot, $interview.epacSuffix))
            $ikey = 'EpacDevelopmentRoot'
            $hashString = $( -join ($ikey, " ", ($testSummarySeparator * ($TerminalWidth - ($ikey.Length + $ival.Length + 2))), " ", $ival))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
            $allInterviewAnswers.Add($ikey, $ival)
            # Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "`nEPAC Development Root: " -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
        }
        Remove-Variable ikey -ErrorAction SilentlyContinue
        Remove-Variable ival -ErrorAction SilentlyContinue
        Remove-Variable loopId -ErrorAction SilentlyContinue
        Remove-Variable loopNotes -ErrorAction SilentlyContinue
        New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime    

        ############
        # policyDecisions Loop
        $loopId = "policyDecisions"
        Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent

        try {
            $interview = New-HydrationAnswerSet -LoopId $loopId -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
        }
        catch {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
            return
        }
        Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
        foreach ($intKey in $interview.keys) {
            $allInterviewAnswers.Add($intKey, $interview.$intKey)
            $testSummarySeparator = "-"
            $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
        }
        Remove-Variable loopId -ErrorAction SilentlyContinue
        Remove-Variable loopNotes -ErrorAction SilentlyContinue
        New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime    

        ############
        # pipelineDecisions Loop
        $loopId = "pipelineDecisions"
        Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent

        try {
            $interview = New-HydrationAnswerSet -LoopId $loopId -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
        }
        catch {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
            return
        }
        Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
        Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
        foreach ($intKey in $interview.keys) {
            $allInterviewAnswers.Add($intKey, $interview.$intKey)
            $testSummarySeparator = "-"
            $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
        }
        # Release flow is too complicated for the current logic, and should be part of a new module generating the pipeline integration with the platform.
        $allInterviewAnswers.Add("pipelineFlow", "Github")
        Remove-Variable loopId -ErrorAction SilentlyContinue
        Remove-Variable loopNotes -ErrorAction SilentlyContinue
        New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime 

        ############
        # otherPipeline Loop

        if ($AllInterviewAnswers.pipelinePlatform -eq "Other") {
            $loopId = "otherPipeline"
            Write-HydrationLogFile -EntryType newStage -EntryData "Processing QuestionSet: $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent

            try {
                $interview = New-HydrationAnswerSet -LoopId $loopId -UseUtc:$UseUtc -LogFilePath $logFilePath  -TerminalWidth:$TerminalWidth -ErrorAction Stop
            }
            catch {
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Failed to process QuestionSet $loopId"  -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
                Write-Error "Error in the interview process for $loopId, please review the error message and rerun the process."
                return
            }
            Write-HydrationLogFile -EntryType answerSetProvided -EntryData "$($interview | Convertto-Json -depth 100 -compress)" -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
            Write-Host "`nQuestion Set is complete, responses outlined below..." -ForegroundColor Yellow
            foreach ($intKey in $interview.keys) {
                $allInterviewAnswers.Add($intKey, $interview.$intKey)
                $testSummarySeparator = "-"
                $hashString = $( -join ($intKey, " ", ($testSummarySeparator * ($TerminalWidth - ($intKey.Length + $($interview.$intKey).Length + 2))), " ", $($interview.$intKey)))
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
            }
            Remove-Variable loopId -ErrorAction SilentlyContinue
            Remove-Variable loopNotes -ErrorAction SilentlyContinue
            New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime 
        }
        else {
            $allInterviewAnswers.Add("pipelineCustomPath", "NotApplicable")
        }
        # Output Answer File
        $writeAnswerFile = $stageBlocks.writeAnswerFile
        New-HydrationSeparatorBlock @writeAnswerFile
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "File Location: $answerFilePath"-LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        try {
            $allInterviewAnswers | ConvertTo-Json -Depth 100 | Set-Content -Path $answerFilePath -Force
        }
        catch {
            Write-Error "Unable to write the answer file to $answerFilePath. Please ensure that you have write access to the location and try again. This was tested during the preliminary checks, so this is an odd situation. It is possible that a write lock, or some other lock, has occurred."
            return
        }
        
        # Summary separator block
        $displayAnswerData = $stageBlocks.displayAnswerData
        New-HydrationSeparatorBlock @displayAnswerData
        Write-HydrationLogFile -EntryType newStage -EntryData $displayAnswerData.DisplayText -LogFilePath $logFilePath -UseUtc:$UseUtc -Silent
    }

    # Display Summary
    $testSummarySeparator = "-"
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Summary:" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    foreach ($hashkey in $allInterviewAnswers.keys) {
        $hashString = $( -join ($hashKey, " ", ($testSummarySeparator * ($TerminalWidth - ($hashKey.Length + $($allInterviewAnswers.$hashKey).Length + 2))), " ", $($allInterviewAnswers.$hashKey)))
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
    }
    New-HydrationContinuePrompt -Interactive:$Interactive -SleepTime:$sleepTime

    # Test New MG Values
    
    try {
        $gatherData.currentTenantPacSelector.caf3Status = $environmentEntry.caf3Status = `
            Test-HydrationCaf3Hierarchy `
            -TenantId $(Get-AzContext).Tenant.Id `
            -TenantIntermediateRoot $TenantIntermediateRoot `
            -MgPrefix:$allInterviewAnswers.mainCaf3Prefix `
            -MgSuffix:$allInterviewAnswers.mainCaf3Suffix `
            -LogFilePath $logFilePath
    }
    catch {
        Write-Error $Error[0].Exception.Message
        return
    }
    try {
        $gatherData.currentTenantPacSelector.caf3Status = $environmentEntry.caf3Status = `
            Test-HydrationCaf3Hierarchy `
            -TenantId $(Get-AzContext).Tenant.Id `
            -TenantIntermediateRoot $TenantIntermediateRoot `
            -MgPrefix:$allInterviewAnswers.epacPrefix `
            -MgSuffix:$allInterviewAnswers.epacSuffix `
            -LogFilePath $logFilePath
    }
    catch {
        Write-Error $Error[0].Exception.Message
        return
    }
    
    ################################################################################
    # Execute hydration process
    Clear-Host
    $blockData = $stageBlocks.beginHydrationProcess
    New-HydrationSeparatorBlock @blockData
    Write-HydrationLogFile -EntryType newStage -EntryData "Hydrating EPAC based on the answers provided below:" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    foreach ($hashkey in $allInterviewAnswers.keys) {
        $hashString = $( -join ($hashKey, " ", ($testSummarySeparator * ($TerminalWidth - ($hashKey.Length + $($allInterviewAnswers.$hashKey).Length + 2))), " ", $($allInterviewAnswers.$hashKey)))
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$hashString" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
    }

    #########################
    # Create Definitions Folder Structure

    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Creating Definitions folder structure..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    try {
        New-HydrationDefinitionsFolder -DefinitionsRootFolder $DefinitionsRootFolder -ErrorAction Stop
    }
    catch {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $Error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Unable to create Definitions folder. Please ensure that you have write access to $(Get-Location) and try again." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Use answer file at $answerFilePath to rerun the script without prompting for questions to retry this process once the problem is resolved." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        return
    }
    Write-Host " Definitions folder structure has been validated..." -ForegroundColor Green

    #########################
    # Create Global Settings File
    # Generate Environment List

    $allInterviewAnswers.initialTenantId = (Get-AzContext).tenant.id
    $allInterviewAnswers.initialTenantCloud = (Get-AzContext).environment.name
    # $allInterviewAnswers.initialTenantIntermediateRoot = $TenantIntermediateRoot
    $globalSettingsInputs = [ordered]@{
        PacOwnerId                 = $allInterviewAnswers.pacOwnerId
        DefinitionsRootFolder      = $DefinitionsRootFolder
        ManagedIdentityLocation    = $allInterviewAnswers.managedIdAssignmentLocation
        MainPacSelector            = $allInterviewAnswers.mainTenantMainPacSelectorName
        EpacPacSelector            = $epacDevName # TODO: Improvement, add a question to the mainpacselector loop for the epacPacSelector
        Cloud                      = (Get-AzContext).environment.name # This never need not be prompted, choice of initialTenantId will choose this implicitly
        TenantId                   = $allInterviewAnswers.initialTenantId
        MainDeploymentRoot         = $allInterviewAnswers.initialTenantIntermediateRoot
        EpacDevelopmentRoot        = $allInterviewAnswers.EpacDevelopmentRoot
        Strategy                   = 'ownedOnly' # This is kept at ownedOnly on purpose. People should be comfortable enough with the deployment to update this before changing to full to help prevent accidents
        # RepoRoot = $(Resolve-Path $DefinitionsRootFolder | Split-Path -Parent)
        LogFilePath                = $logFilePath
        UseUtc                     = $UseUtc
        KeepDfcSecurityAssignments = $false # TODO: Improvement, add a question to the mainpacselector loop for the dfcSecurityAssignments
    }
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Creating Global Settings file..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    try {
        $null = New-HydrationGlobalSettingsFile @globalSettingsInputs  -ErrorAction Stop
    }
    catch {
        Write-Error "Unable to create global-settings file. This is likely a flaw in the choices made above that should have been caught in earlier tests. Please retain your answer file and report this to the EPAC team, and attempt this process again."
        return
    }
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Creating Pipeline..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    Remove-Variable usePipelineCustomPath -ErrorAction SilentlyContinue
    if ($allInterviewAnswers.pipelineCustomPath -eq "NotApplicable"){
        try {
            if($allInterviewAnswers.codeExecutionType -eq "Scripts"){
                if(Test-Path $(Join-Path $repoRootPath "Scripts" "Operations" "New-PipelinesFromStarterKit.ps1")) {
                    & (Join-Path $repoRootPath "Scripts" "Operations" "New-PipelinesFromStarterKit.ps1") -StarterKitFolder $exportedDefinitionsPath.starterKit `
                        -PipelineType $allInterviewAnswers.pipelinePlatform `
                        -BranchingFlow $allInterviewAnswers.pipelineFlow `
                        -ScriptType $allInterviewAnswers.codeExecutionType `
                        -ErrorAction Stop `
                        -SuppressConfirm:$true
                }elseif(Test-Path (Join-Path $repoRootPath "temp" "Scripts" "Operations" "New-PipelinesFromStarterKit.ps1")){
                    & (Join-Path $repoRootPath "temp" "Scripts" "Operations" "New-PipelinesFromStarterKit.ps1") -StarterKitFolder $exportedDefinitionsPath.starterKit `
                        -PipelineType $allInterviewAnswers.pipelinePlatform `
                        -BranchingFlow $allInterviewAnswers.pipelineFlow `
                        -ScriptType $allInterviewAnswers.codeExecutionType `
                        -ErrorAction Stop `
                        -SuppressConfirm:$true
                }
            }
            elseif($allInterviewAnswers.codeExecutionType -eq "Module"){
                New-PipelinesFromStarterKit -StarterKitFolder $exportedDefinitionsPath.starterKit `
                    -PipelineType $allInterviewAnswers.pipelinePlatform `
                    -BranchingFlow $allInterviewAnswers.pipelineFlow `
                    -ScriptType $allInterviewAnswers.codeExecutionType `
                    -ErrorAction Stop `
                    -SuppressConfirm:$true
            }
        }
        catch {
            Write-Host "Failure, Error Information: $($_.Exception.Message)" -ForegroundColor Red
            Write-Error "Unable to create pipeline. This is likely a flaw in the choices made above that should have been caught in earlier tests. Please retain your answer file and report this to the EPAC team, and attempt this process again."
            return
        }
    }
    else {
        try {
            if(Test-Path $(Join-Path $repoRootPath "Scripts" "Operations" "New-PipelinesFromStarterKit.ps1")) {
                & (Join-Path $repoRootPath "Scripts" "Operations" "New-PipelinesFromStarterKit.ps1") -StarterKitFolder $exportedDefinitionsPath.starterKit `
                -PipelinesFolder:$usePipelineCustomPath `
                -PipelineType $allInterviewAnswers.pipelinePlatform `
                -BranchingFlow $allInterviewAnswers.pipelineFlow `
                -ScriptType $allInterviewAnswers.codeExecutionType `
                -ErrorAction Stop `
                -SuppressConfirm:$true
            }elseif(Test-Path "./Scripts/Operations/New-PipelinesFromStarterKit.ps1"){
                & "./Scripts/Operations/New-PipelinesFromStarterKit.ps1" -StarterKitFolder $exportedDefinitionsPath.starterKit `
                -PipelinesFolder:$usePipelineCustomPath `
                -PipelineType $allInterviewAnswers.pipelinePlatform `
                -BranchingFlow $allInterviewAnswers.pipelineFlow `
                -ScriptType $allInterviewAnswers.codeExecutionType `
                -ErrorAction Stop
            }else{
                New-PipelinesFromStarterKit -StarterKitFolder $exportedDefinitionsPath.starterKit `
                -PipelinesFolder:$usePipelineCustomPath `
                -PipelineType $allInterviewAnswers.pipelinePlatform `
                -BranchingFlow $allInterviewAnswers.pipelineFlow `
                -ScriptType $allInterviewAnswers.codeExecutionType `
                -ErrorAction Stop
            }
        }
        catch {
            Write-Error "Unable to create pipeline. This is likely a flaw in the choices made above that should have been caught in earlier tests. Please retain your answer file and report this to the EPAC team, and attempt this process again."
            return
        }

    }


    ## Build MG Structure
    if ($allInterviewAnswers.createMainIntermediateRoot -eq "Yes") {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Creating Main Intermediate Root..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        do {
            try {
                New-AzManagementGroup -GroupName $allInterviewAnswers.initialTenantIntermediateRoot -ErrorAction Stop
            }
            catch {
                $AzMgRetry = $true
            }
            if (Get-AzManagementGroupRestMethod -GroupId $allInterviewAnswers.initialTenantIntermediateRoot) {
                $AzMgRetry = $false
            }

        }until($AzMgRetry -eq $false)
    }
    if ($allInterviewAnswers.createMainCaf3Hierarchy -eq "Yes") {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Creating Main CAF3 Management Groups..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        New-HydrationCaf3Hierarchy -DestinationRootName $allInterviewAnswers.initialTenantIntermediateRoot -Prefix $allInterviewAnswers.mainCaf3Prefix -Suffix $allInterviewAnswers.maincaf3Suffix
        $updatedTenantIntermediateRoot =  $allInterviewAnswers.initialTenantIntermediateRoot
    }
    ## Build EPAC MG Structure
    if (!($skipEpacMgDeploy)) {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Creating Epac Management Groups in $(-join($allInterviewAnswers.epacPrefix,$allInterviewAnswers.initialTenantIntermediateRoot,$allInterviewAnswers.epacSuffix)), a child of $($allInterviewAnswers.epacParent)..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        Copy-HydrationManagementGroupHierarchy -SourceGroupName  $allInterviewAnswers.initialTenantIntermediateRoot -DestinationParentGroupName $allInterviewAnswers.epacParent -Prefix:$allInterviewAnswers.epacPrefix -Suffix:$allInterviewAnswers.epacSuffix | Out-Null
    }


    ## Import Existing Policy Assignments (if applicable)
    if ($allInterviewAnswers.importExistingPolicies -eq "Yes") {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Importing Existing Policy Assignments..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Exporting existing content for PacSelector `'$($allInterviewAnswers.mainTenantMainPacSelectorName)`', for which the root is defined as $( $allInterviewAnswers.initialTenantIntermediateRoot)" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        try{
            if(Test-Path $(Join-Path $repoRootPath "Scripts" "Operations" "Export-AzPolicyResources.ps1")) {
                & (Join-Path "$repoRootPath" "Scripts" "Operations" "Export-AzPolicyResources.ps1") -DefinitionsRootFolder $DefinitionsRootFolder `
                -ExemptionFiles 'csv' `
                -FileExtension 'jsonc' `
                -IncludeAutoAssigned `
                -IncludeChildScopes `
                -InputPacSelector $allInterviewAnswers.mainTenantMainPacSelectorName `
                -Mode 'export' `
                -OutputFolder $Output `
                -Interactive:$FALSE `
                -ErrorAction Stop
            }elseif(Test-Path $(Join-Path $repoRootPath "temp" "Scripts" "Operations" "Export-AzPolicyResources.ps1")){
                & (Join-Path "$repoRootPath" "temp" "Scripts" "Operations" "Export-AzPolicyResources.ps1") -DefinitionsRootFolder $DefinitionsRootFolder `
                -ExemptionFiles 'csv' `
                -FileExtension 'jsonc' `
                -IncludeAutoAssigned `
                -IncludeChildScopes `
                -InputPacSelector $allInterviewAnswers.mainTenantMainPacSelectorName `
                -Mode 'export' `
                -OutputFolder $Output `
                -Interactive:$FALSE `
                -ErrorAction Stop
            }else{
                Export-AzPolicyResources.ps1 -DefinitionsRootFolder $DefinitionsRootFolder `
                    -ExemptionFiles 'csv' `
                    -FileExtension 'jsonc' `
                    -IncludeAutoAssigned `
                    -IncludeChildScopes `
                    -InputPacSelector $allInterviewAnswers.mainTenantMainPacSelectorName `
                    -Mode 'export' `
                    -OutputFolder $Output `
                    -Interactive:$FALSE `
                    -ErrorAction Stop
            }
        }catch{
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $Error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
            return
        }

        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Export process complete. Copying non-assignment content to definitions folder..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        # Rename to align with naming expected by Export-PolicyToEPAC, simplifies linux support.
        Rename-Item -Path (Join-Path $Output "export") -NewName "Export" -Force -ErrorAction SilentlyContinue
        # $exportedDefinitionsPath = Join-Path $Output "Export" "Definitions"
        if (!(Test-Path $exportedDefinitionsPath.definitions)) {
            Write-Error "Unable to find the folder $($exportedDefinitionsPath.definitions). You should go to https://portal.azure.com and confirm whether or not assignments exist that are assigned within the referenced scope $($answerFilePath.initialTenantIntermediateRoot) and its children."
            $noExport = Read-Host "Type 'Confirmed' and press enter to continue, otherwise simply press enter to quit..."
            if (!($noExport -eq "Confirmed")) {
                {
                    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "You have confirmed that the export does not contain your contents. Confirm access, and run the script again, choosing to use the answer file at $answerFilePath." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
                }
            }
        }
        elseif (Test-Path $exportedDefinitionsPath.definitions) { # This should be triggered now
            $nonAssignmentExportFolders = Get-ChildItem $exportedDefinitionsPath.definitions -Directory -Exclude policyAssignments
            if ($nonAssignmentExportFolders.count -gt 0) {
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Copying $($nonAssignmentExportFolders.count) non-assignment content to definitions folder..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
                foreach ($sourceDir in $nonAssignmentExportFolders) {
                    $updatedFiles = Get-ChildItem -Path $sourceDir -Recurse -Include "*.json", "*.jsonc", '*.csv'
                    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Copying content from $sourceDir to $DefinitionsRootFolder" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
                    foreach ($uFile in $updatedFiles) {
                        # Calculate the relative path of the item
                        $relativePath = $uFile.FullName.Substring($(Split-Path $sourceDir.FullName).Length + 1)
                        
                        # Create the full destination path
                        $destinationPath = Join-Path -Path $DefinitionsRootFolder -ChildPath $relativePath

                        # Create the necessary destination directories
                        $destinationDirPath = Split-Path -Path $destinationPath
                        if (!(Test-Path -Path $destinationDirPath)) {
                            $null = New-Item -Path $destinationDirPath -ItemType Directory
                            Write-HydrationLogFile -EntryType logEntryDataAsPresented `
                                -EntryData " Created $destinationDirPath" `
                                -LogFilePath $logFilePath `
                                -UseUtc:$UseUtc `
                                -Silent
                        }
                        # Copy the file or directory
                        Copy-Item -Path $uFile.FullName -Destination $destinationPath -Force
                        Write-HydrationLogFile -EntryType logEntryDataAsPresented `
                            -EntryData " Copied $uFile to $destinationPath" `
                            -LogFilePath $logFilePath `
                            -UseUtc:$UseUtc `
                            -Silent
                        if (!(Test-Path -Path $destinationPath)) {
                            Write-HydrationLogFile -EntryType logEntryDataAsPresented `
                                -EntryData " Failed to copy $uFile to $destinationPath, this should be copied manually or the task should be run again." `
                                -LogFilePath $logFilePath `
                                -UseUtc:$UseUtc `
                                -ForegroundColor Red
                        }
                    }
                }
            }
            else{
                Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " No non-assignment content found to copy." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
            }
        }
        Remove-Variable noExport -ErrorAction SilentlyContinue
    }

    # Add Audit standards at root of hierarchies
    # if ($allInterviewAnswers.importPciDssPolicies -eq "Yes" -or $allInterviewAnswers.importMcsbPolicies -eq "Yes" -or $allInterviewAnswers.importNist80053Policies -eq "Yes") {
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Adding Specified PolicySet and (optional) Policy defintions" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    $auditStandardList = @("/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8")
    if ($allInterviewAnswers.importPciDssPolicies -eq "Yes") {
        $auditStandardList += "/providers/Microsoft.Authorization/policySetDefinitions/c676748e-3af9-4e22-bc28-50feed564afb"
    }
    if ($allInterviewAnswers.importNist80053Policies -eq "Yes") {
        $auditStandardList += "/providers/Microsoft.Authorization/policySetDefinitions/179d1daa-458f-4e47-8086-2a68d0d6c38f"
    }
    if ($allInterviewAnswers.importAdditionalPolicySets) {
        $splitList = $allInterviewAnswers.importAdditionalPolicySets -split ","
        foreach ($guid in $splitList) {
            # Note: Rather than supporting questions about whether or not "" are appropriate for wrapping the GUID, we just manage it with RegEx.
            $guid = $guid -replace '[,"'' ]', ''
            $parsedGuid = [System.Guid]::Empty
            if (-not [System.Guid]::TryParse($guid, [ref]$parsedGuid)) {
                Write-Error "$guid is not a valid GUID, skipping..."
            }
            else {
                $auditStandardList += "/providers/Microsoft.Authorization/policySetDefinitions/$guid"
            }
        }
    }
    foreach ($polSet in $auditStandardList) {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Exporting $polSet" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        $lCount = 0
        do {
            $succ1 = $true
            try {
                if ($gatherData.policySetDefinitions.name -contains $($polSet.split("/")[-1])) {
                    # Handle Scripts based install
                    if(Test-Path $(Join-Path $repoRootPath "Scripts" "Operations" "Export-PolicyToEPAC.ps1")) {
                        & (Join-Path "$repoRootPath" "Scripts" "Operations" "Export-PolicyToEPAC.ps1") -PolicySetDefinitionId $polSet `
                            -OutputFolder $Output  `
                            -AutoCreateParameters $TRUE  `
                            -UseBuiltIn $TRUE  `
                            -OverwriteScope $(@("/providers/Microsoft.Management/managementGroups",  $allInterviewAnswers.initialTenantIntermediateRoot) -join "/")  `
                            -OverwritePacSelector $allInterviewAnswers.mainTenantMainPacSelectorName  `
                            -OverwriteOutput $FALSE -ErrorAction Stop
                    }elseif(Test-Path $(Join-Path $repoRootPath "temp" "Scripts" "Operations" "Export-PolicyToEPAC.ps1")){
                        & (Join-Path "$repoRootPath" "temp" "Scripts" "Operations" "Export-PolicyToEPAC.ps1") -PolicySetDefinitionId $polSet `
                            -OutputFolder $Output  `
                            -AutoCreateParameters $TRUE  `
                            -UseBuiltIn $TRUE  `
                            -OverwriteScope $(@("/providers/Microsoft.Management/managementGroups",  $allInterviewAnswers.initialTenantIntermediateRoot) -join "/")  `
                            -OverwritePacSelector $allInterviewAnswers.mainTenantMainPacSelectorName  `
                            -OverwriteOutput $FALSE -ErrorAction Stop
                    }else{
                        Export-PolicyToEPAC -PolicySetDefinitionId $polSet `
                            -OutputFolder $Output  `
                            -AutoCreateParameters $TRUE  `
                            -UseBuiltIn $TRUE  `
                            -OverwriteScope $(@("/providers/Microsoft.Management/managementGroups",  $allInterviewAnswers.initialTenantIntermediateRoot) -join "/")  `
                            -OverwritePacSelector $allInterviewAnswers.mainTenantMainPacSelectorName  `
                            -OverwriteOutput $FALSE -ErrorAction Stop
                    }
                }
                elseif ($gatherData.policyDefinitions.name -contains $($polSet.split("/")[-1])) {
                    Export-PolicyToEPAC -PolicyDefinitionId $polSet `
                        -OutputFolder $Output  `
                        -AutoCreateParameters $TRUE `
                        -UseBuiltIn $TRUE `
                        -OverwriteScope $(@("/providers/Microsoft.Management/managementGroups",  $allInterviewAnswers.initialTenantIntermediateRoot) -join "/") `
                        -OverwritePacSelector $allInterviewAnswers.mainTenantMainPacSelectorName `
                        -OverwriteOutput $FALSE `
                        -ErrorAction Stop
                }
                else {
                    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " PolicySet or PolicyDefinition does not appear to be a valid built-in policySet, skipping..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red  
                }
            }
            catch {
                $succ1 = $false
                $lCount++
            }
        }until($succ1 -eq $true -or $lCount -gt 5)
        if (!($succ1)) {
            Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Failed to Export Current Azure Policy Assignments. Confirm access level and pressence of assignments to export." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow     
        }
    }
    if(!(Test-Path $exportedDefinitionsPath.policyAssignments)){
       $null = New-Item -Path $exportedDefinitionsPath.policyAssignments -ItemType Directory -Force -ErrorAction SilentlyContinue
    }
    Move-Item -Path $(Join-Path $exportedDefinitionsPath.exportPolicyToEpac "*") -Destination $exportedDefinitionsPath.policyAssignments -Force -ErrorAction SilentlyContinue
    Remove-Item -Path $exportedDefinitionsPath.exportPolicyToEpac -Force -ErrorAction SilentlyContinue
    Copy-Item -Path $(Join-Path $exportedDefinitionsPath.policyAssignments "*") -Destination $(Join-Path -Path $DefinitionsRootFolder "policyAssignments") -Recurse -Force
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Copied exported assignments to Definitions folder structure..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    try{New-HydrationAssignmentPacSelector -SourcePacSelector $allInterviewAnswers.mainTenantMainPacSelectorName `
        -NewPacSelector $epacDevName `
        -MGHierarchyPrefix:$allInterviewAnswers.epacPrefix `
        -MGHierarchySuffix:$allInterviewAnswers.epacSuffix `
        -Definitions $DefinitionsRootFolder `
        -Output $Output `
        -ErrorAction Stop
    }
    catch{
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData $Error[0].Exception.Message -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
        return
    }
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Updated exported and newly created assignments with epac-dev pacSelector information based on assignments in PacSelector `'$($allInterviewAnswers.mainTenantMainPacSelectorName)...`'" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
    if ((Get-ChildItem  $(Join-Path $Output "UpdatedAssignments")).count -gt 0) {
        Copy-Item -Path $(Join-Path $Output "UpdatedAssignments" "*") -Destination $(Join-Path -Path $DefinitionsRootFolder "policyAssignments") -Recurse -Force
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Copied updated assignments to Definitions folder structure..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        # $updatedAssignmentList = Get-ChildItem -Path $(Join-Path $Output "UpdatedAssignments") -Recurse -Include "*.json", "*.jsonc" -ErrorAction SilentlyContinue
        # if ($updatedAssignmentList.count -gt 0) {
        # Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData " Copying updated $($UpdatedAssignmentList.count) assignments to definitions folder..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        # Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Copying new content to $DefinitionsRootFolder" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        # }

    }
    else {
        Write-HydrationLogFile -EntryType logEntryDataAsPresented `
            -EntryData " No updated assignments found, skipping assignment update, but it is recommended that that you consider running this again with choices that include generation of an assignment so you have a template to review..." `
            -LogFilePath $logFilePath `
            -UseUtc:$UseUtc `
            -ForegroundColor Yellow
    }
    ################################################################################
    # Closing Tasks
    # Clear-Host
    New-HydrationSeparatorBlock -DisplayText "End Hydration Process" -Location Bottom
    Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Hydration process complete." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Magenta
    
    ################################################################################
    # Test in EPAC-Dev

    New-HydrationSeparatorBlock -DisplayText "Deploy to epac-dev" -Location Top

    Write-Host "These steps require that the Az and EnterprisePolicyAsCode modules be available" -ForegroundColor Yellow
    Write-Host "When you are ready to deploy the changes to epac-dev, please perform the following tasks to complete deployment to the $epacDevName pacSelector:" -ForegroundColor Yellow
    Write-Host " Build-DeploymentPlans -PacEnvironmentSelector $epacDevName -OutputFolder $Output -DefinitionsRootFolder $DefinitionsRootFolder"
    Write-Host " Deploy-PolicyPlan -PacEnvironmentSelector $epacDevName -DefinitionsRootFolder $DefinitionsRootFolder"
    Write-Host " Deploy-RolesPlan -PacEnvironmentSelector $epacDevName -DefinitionsRootFolder $DefinitionsRootFolder"
    Write-Host "`nIf you were notified that default values were missing for items above (scroll back to review), you will need to update those values prior to running the code above." -BackgroundColor Yellow -ForegroundColor Black
    Write-Host "`n"
    Write-Host "Parameter Update Guidance: https://github.com/Azure/enterprise-azure-policy-as-code/blob/main/Docs/policy-assignments.md"
    Write-Host "Advanced Parameter Management Guidance: https://github.com/Azure/enterprise-azure-policy-as-code/blob/main/Docs/policy-assignments-csv-parameters.md"

    Write-Host "`nNext Steps: CI/CD Integration" -ForegroundColor Yellow
    Write-Host " General Guidance: https://azure.github.io/enterprise-azure-policy-as-code/ci-cd-overview/"
    Write-Host " Branching Flow Guidance: https://github.com/Azure/enterprise-azure-policy-as-code/blob/main/Docs/ci-cd-branching-flows.md"
    Write-Host " Review high level CI/CD Options. While the hydration kit only supports a standard two stage deployment plan, you may want to consider a release plan for your environment."
    Write-Host " Azure DevOps: https://azure.github.io/enterprise-azure-policy-as-code/ci-cd-ado-pipelines/"
    Write-Host " Review Azure DevOps Pipeline implementation options and guidance."
    Write-Host " GitHub Actions: https://azure.github.io/enterprise-azure-policy-as-code/ci-cd-github-actions/"
    Write-Host " Review Github Actions implementation options and guidance."
    Write-Host "`nNext Steps: Additional Policy Assignments" -ForegroundColor Yellow    
    Write-Host " Sync-AlzPolicies: https://github.com/Azure/enterprise-azure-policy-as-code/blob/main/Docs/integrating-with-alz.md#scenario-2---alz-policy-deployment-with-epac" 
    Write-Host " Import the ALZ Policy Set using Sync-AlzPolicies, and update the parameters which do not have default values to add policies that will aid in modification of your environment to baseline Microsoft standards."
    Write-Host " Create Additional Assignments: https://github.com/Azure/enterprise-azure-policy-as-code/blob/main/Docs/operational-scripts.md"
    Write-Host " Review the command Export-PolicyToEPAC to simplify additional assignment creation.`n"
    Write-Host "Type 'CleanUp' to delete temporary files created during this process, or simply press enter to retain them for review..." -foregroundColor Yellow -BackgroundColor Black
    if($Interactive){$cleanupOption = Read-Host "`nCleanup?"}
    if ($cleanupOption -eq "CleanUp") {
        Remove-Item -Path $(Join-Path $repoRootPath "temp") -Recurse -Force -ErrorAction SilentlyContinue
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Temporary files removed." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
    }
    else{
        Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Temporary files retained at $(Join-Path $repoRootPath "temp") for review." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
        Write-Host "Task Complete!" -ForegroundColor Green
    }
    Write-Host "Output files retained at $(Join-Path $repoRootPath "Output") for review, but are excluded from replication to the repo." -ForegroundColor Green
    return
}