$RootPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent

. $RootPath\AnywhereNow\Scripts\Shared.ps1
. $RootPath\AnywhereNow\Scripts\SharedPnpFunctions.ps1
. $RootPath\AnywhereNow\Scripts\WSP.UCC-0.Update.ps1
. $RootPath\AnywhereNow\Scripts\WSP.UCC-3.SubSite.ps1
. $RootPath\AnywhereNow\Scripts\WSP.UCC-4.Lists.ps1
. $RootPath\AnywhereNow\Scripts\WSP.UCC-5.ColumnsContentTypes.ps1
. $RootPath\AnywhereNow\Scripts\WSP.UCC-6.Views.ps1
. $RootPath\AnywhereNow\Scripts\WSP.UCC-7.ListContent.ps1

function GetSubSiteUrl($siteName, $parentSitePath)
{
	if ($useSubSites)
	{
		if (-not [string]::IsNullOrEmpty($parentSitePath))
		{
			# Parent site specified (from A365_ParentSite field) — create under that parent
			$parentSitePath = $parentSitePath.Trim('/')
			$parentWebUrl   = $scurl + "/" + $parentSitePath
			$siteUrl        = $parentWebUrl + "/" + $siteName
			$parentSiteUrl  = $parentWebUrl
		}
		else
		{
			# No parent specified — create directly under site collection root
			$siteUrl       = $scurl + "/" + $siteName
			$parentSiteUrl = $scurl
		}
	}
	else
	{
		# Subsites disabled — always deploy to site collection root
		$siteUrl       = $scurl
		$parentSiteUrl = $scurl
	}

	$siteUrl
	$parentSiteUrl
}

function EnsureSite 
{
    Param(
        [string]$siteEntryId,
        [string]$uccName,
        [string]$siteUrl,
        [string]$description = ""
    )
}

function UpdateStatus($id, $status) 
{
    Connect $ctx.Url | Out-Null
	SetPnPListItem $siteDirectoryList $id @{"$($columnPrefix)SiteStatus" = $status}
}

function GetStatus($id) 
{
	Connect $ctx.Url | Out-Null
    $items = Get-PnPListItem -List $siteDirectoryList -Id $id -Fields A365_SiteStatus
    $item = $items | % {new-object PSObject -Property @{A365_SiteStatus = $_["A365_SiteStatus"]}} | select A365_SiteStatus
    return $item.A365_SiteStatus
}

function UpdateUccName($id, $updateUccName) 
{
    Connect $ctx.Url | Out-Null
	$updateUccName = $updateUccName.ToLower() -replace '[^a-z0-9_.-]'
    SetPnPListItem $siteDirectoryList $id @{"Title" = $updateUccName}
}

function SetSiteUrl($siteItem, $siteUrl, $updateUccName) 
{
    Connect $ctx.Url | Out-Null
	$updateUccName = $updateUccName.ToLower() -replace '[^a-z0-9_.-]'
	SetPnPListItem $siteDirectoryList $siteItem["ID"] @{"$($columnPrefix)SiteURL" = "$siteUrl, $updateUccName"}
}

function GetSiteToProvision
{
	Connect $ctx.Url | Out-Null
	# Return ALL items with status "Requested" — enables batch processing of multiple pending requests
	$siteProvisionQuery = @"
<View>
    <Query>
        <Where>
            <Eq>
                <FieldRef Name="A365_SiteStatus" />
                <Value Type="Text">Requested</Value>
            </Eq>
        </Where>
        <OrderBy>
            <FieldRef Name="ID" Ascending="True" />
        </OrderBy>
    </Query>
    <ViewFields>
        <FieldRef Name="ID" />
        <FieldRef Name="Title" />
        <FieldRef Name="A365_SiteStatus" />
        <FieldRef Name="A365_ParentSite" />
    </ViewFields>
</View>
"@

	return @(Get-PnPListItem -List $siteDirectoryList -Query $siteProvisionQuery)
}

function ApplyTemplate
{
	$hasTemplate = $false
	$connected = Connect -Url $siteUrl
	if ($connected)
	{
		if ($resetTemplateFlag)
		{
			try
			{
				Remove-PnPPropertyBagValue -Key $propBagTemplateNameStampKey -Force
			}
			catch
			{
			}
		}
		else
		{
			$hasTemplate = CheckPnPPropertyBag $propBagTemplateNameStampKey
		}
	}
	else
	{
		Connect $ctx.Url | Out-Null
	}

    if (!$hasTemplate) 
	{
		# Normalize ucc name
		UpdateUccName $siteItem["ID"] $uccName
		# Create site
		UpdateStatus $siteItem["ID"] "1/7 Creating Site"
		CreateTemplateSite
		# Create lists
		UpdateStatus $siteItem["ID"] "2/7 Lists"
		Connect $siteUrl | Out-Null
		CreateLists
		# Create columns & content types
		UpdateStatus $siteItem["ID"] "3/7 Site Columns & Content Types"
		Connect $siteUrl | Out-Null
		CreateColumnsAndContentTypes
		# Content Types to Lists & Views
		UpdateStatus $siteItem["ID"] "4/7 Content Types to Lists & Views"
		Connect $siteUrl | Out-Null
		AddCtAndViews
		# List content
		UpdateStatus $siteItem["ID"] "5/7 List Content"
		Connect $siteUrl | Out-Null
		SetListContent
		# Apply patches
		UpdateStatus $siteItem["ID"] "6/7 Apply Patches"
		Connect $siteUrl | Out-Null
		ExecuteNewSiteUpdate
		# Reconnect lookups
		UpdateStatus $siteItem["ID"] "7/7 (Re)Connect Lookup Columns"
		FixLookups           
        # Set propertybag
		SetPnPPropertyBagValue $propBagTemplateNameStampKey $propBagTemplateInfoStampKey
    }

	Disconnect-PnPOnline
	Connect $ctx.Url | Out-Null
}

function ProcessSiteToProvision($siteDirectoryItem)
{
	if ($siteDirectoryItem -eq $null) 
	{
		$uccName = TrimValue $paramUccName
		$uccTitle = TrimValue $paramUccTitle

		$siteUrl = ""
		$language = TrimValue $paramLanguage
		if ([string]::IsNullOrEmpty($language))
		{
			$language = "English"
		}
		else 
		{
			$languageInfo = GetLanguage($language)
			$language = $languageInfo[2]
		}

		$cdrConnectionString = TrimValue $paramCdrConnectionString
		$listParentSite = $null  # No list item — subsite mode always uses list-driven path

		$query = "<View><Query><Where><Eq><FieldRef Name='Title' /><Value Type='Text'>$uccName</Value></Eq></Where></Query><ViewFields><FieldRef Name='ID' /><FieldRef Name='A365_SiteStatus' /></ViewFields></View>"
		$siteItem = Get-PnPListItem -List $siteDirectoryList -Query $query
		if ($siteItem -eq $null) 
		{
			AddPnPListItem $siteDirectoryList @{"Title" = $uccName; "$($columnPrefix)SiteTitle" = $uccTitle; "$($columnPrefix)Language" = $language; "$($columnPrefix)CDRConnectionString" = $cdrConnectionString}
			$siteItem = Get-PnPListItem -List $siteDirectoryList -Query $query
		}

		$siteStatus = $siteItem["$($columnPrefix)SiteStatus"]
		if ($siteStatus -eq "Requested")
		{
			Info "Site creator started"
			UpdateStatus $siteItem.ID "Processing"
			$siteItem = Get-PnPListItem -List $siteDirectoryList -Id $siteItem.ID
		}
		else 
		{
			Write-Host "Site already requested" -ForegroundColor Yellow
			return
		}
	}
	else
	{
		UpdateStatus $siteDirectoryItem.ID "Processing"
		$siteItem = Get-PnPListItem -List $siteDirectoryList -Id $siteDirectoryItem.ID
		$uccName            = $siteItem["Title"]
		$uccTitle           = $siteItem["$($columnPrefix)SiteTitle"]
		$language           = $siteItem["$($columnPrefix)Language"]
		$timeZone           = $siteItem["$($columnPrefix)TimeZone"]
		$cdrConnectionString = $siteItem["$($columnPrefix)CDRConnectionString"]
		$siteUrl            = $siteItem["$($columnPrefix)SiteURL"].Url
		$listParentSite     = $siteItem["$($columnPrefix)ParentSite"]
		$uccName            = TrimValue $uccName
		$uccTitle           = TrimValue $uccTitle
		$language           = TrimValue $language
		$timeZone           = TrimValue $timeZone
		$cdrConnectionString = TrimValue $cdrConnectionString
		$siteUrl            = TrimValue $siteUrl
		$listParentSite     = TrimValue $listParentSite
	}

	$uccName = $uccName -replace "\s", ""
	$uccName = $uccName.ToLower() -replace '[^a-z0-9_.-]'
	if ([string]::IsNullOrEmpty($siteUrl))
	{
		# Pass the A365_ParentSite value (if set) to construct the correct parent web URL
		$returnObject  = GetSubSiteUrl $uccName $listParentSite
		$siteUrl       = $returnObject[0]
		$parentSiteUrl = $returnObject[1]
	}
	else
	{
		# siteUrl already set from the list — still resolve parentSiteUrl for subsite creation
		if ($useSubSites -and -not [string]::IsNullOrEmpty($listParentSite))
		{
			$parentSiteUrl = $scurl + "/" + $listParentSite.Trim('/')
		}
		else
		{
			$parentSiteUrl = $scurl
		}
	}

	$siteStatus = $siteItem["$($columnPrefix)SiteStatus"]

	Info "Processing $siteUrl"

	EnsureSite -siteEntryId $siteItem["ID"] -title $uccName -siteUrl $siteUrl -description $description

	if ($? -eq $true -and ($siteStatus -eq "Processing")) 
	{
		ApplyTemplate

		$siteStatus = GetStatus $siteItem["ID"]
		if ($siteStatus -ne "Provisioned")
		{
			SetSiteUrl $siteItem $siteUrl $uccName
			$provisionStatus = "Provisioned"
			if ($siteStatus.ToLower() -like "*error*")
			{
				$provisionStatus = "Provisioned with errors. See log for details."
			}

			UpdateStatus $siteItem["ID"] $provisionStatus

			# Record the parent site path (relative) in the UCC Creator list when in subsite mode
			if ($useSubSites -and -not [string]::IsNullOrEmpty($listParentSite))
			{
				try
				{
					Connect $ctx.Url | Out-Null
					SetPnPListItem $siteDirectoryList $siteItem["ID"] @{"$($columnPrefix)ParentSite" = $listParentSite}
				}
				catch
				{
					Warn "Could not set A365_ParentSite: $($_.Exception.Message)"
				}
			}

			# Track deployed URL for dashboard deployment loop in UCC.Site.Creator.ps1
			if ($null -eq $global:deployedSiteUrls) { $global:deployedSiteUrls = @() }
			$global:deployedSiteUrls += $siteUrl

			Info $provisionStatus
		}        
	}
}

function CreateSite
{
	# Check vars
	$checkVars = CheckEnvironmentalVariables
	if ($checkVars -eq $false) 
	{
		Warn "Required variables not set. Certificate authentication is required."
		return
	}

	if ($useSubSites)
	{
		Info "UCC Site will be deployed as subsite under: $scurl"
	}
	else
	{
		Info "UCC Site will be deployed to site collection root: $scurl"
	}

	$connected = Connect -Url $scurl -ShowError
	if ($connected -eq $false) 
	{
		Warn "Cannot connect to sitecollection $scurl"
		return
	}

	# Check for NoScript mode - warning only, don't block
	if (!$(CheckDenyAddCustomisePagesFeature)) 
	{
		Warn "Custom Script is disabled. Classic portal.aspx will not work - use SPFx Portal Web Part instead."
	}

	$ctx = Get-PnPContext

	if (![string]::IsNullOrEmpty($paramUccName) -and ![string]::IsNullOrEmpty($paramUccTitle))
	{
		ProcessSiteToProvision
	}
	else 
	{
		$siteDirectoryItems = @(GetSiteToProvision | Where-Object { $_ -ne $null })
		if ($siteDirectoryItems.Count -eq 0)
		{
			Write-Host "No site requests detected" -ForegroundColor Yellow
		}
		else
		{
			$total = $siteDirectoryItems.Count
			$i = 0
			foreach ($siteDirectoryItem in $siteDirectoryItems)
			{
				$i++
				Info "[$i / $total] Processing request ID $($siteDirectoryItem.Id)..."
				Connect -Url $scurl | Out-Null
				$ctx = Get-PnPContext
				ProcessSiteToProvision $siteDirectoryItem
			}
		}
	}

	Disconnect-PnPOnline
}
