<?php
$_db_migration_to = '39.03'; // 8.13.0-beta
if (!isset($migrations) || !is_object($migrations))
	die("This file cannot be executed directly");
$migrations->CheckValid($_db_migration_to);
//===========================================================================================



$migrations->Run('01_style_asset_storage_data_structure_migration.php', <<<'DB_UPDATE_FILE'
<?php
/*
 * Idempotent Migration for updating Themes/the Master Design to a format where the URL for Style assets is derived from their expected locations.
 * This migration will move any assets that do not currently follow the standard format.
 */

/** @var \Claromentis\Setup\SetupFacade $migrations */

$db  = $migrations->GetDb();
$cdn = \Claromentis\Core\Services::I()->GetCDN();

if (!function_exists('updateStyleStorageData'))
{
	/**
	 * Given a Style's data,
	 * updates the format of data for logos, favicons and backgrounds.
	 *
	 * Returns the updated Style's data.
	 *
	 * @param array                              $style
	 * @param string                             $styleCode
	 * @param \Claromentis\Core\CDN\CDNInterface $cdn
	 * @return array
	 */
	function updateStyleStorageData(array $style, string $styleCode, \Claromentis\Core\CDN\CDNInterface $cdn, \Claromentis\Setup\SetupFacade $migrations): array
	{
		$backgroundSizes = ['FHD', '2.7k', '4k UHD'];

		if (isset($style['logo_url']) && is_string($style['logo_url']))
		{
			try {
				$cdnPath = getStyleAssetCdnPath($style['logo_url']);
				$migrations->Log("Renaming logo: '$style[logo_url]', '$cdnPath', '$styleCode'");
				$newCdnPath = renameStyleLogo($cdnPath, $styleCode, $cdn);
				$migrations->Log("New logo path: '$newCdnPath'");
				$style['logo_extension'] = pathinfo($newCdnPath, PATHINFO_EXTENSION);
			} catch (\Exception $e) {
				$migrations->Log("Failed to update logo for '$styleCode': " . $e->getMessage());
				$migrations->Log((string) $e);
			}
			unset($style['logo_url']);
		}

		if (isset($style['favicon']) && is_array($style['favicon']))
		{
			foreach ($style['favicon'] as $resolution => $url)
			{
				try {
					$cdnPath = getStyleAssetCdnPath($url);
					$migrations->Log("Renaming favicon: '$url', '$cdnPath', '$resolution', '$styleCode'");
					$newCdnPath = renameStyleFavicon($cdnPath, $resolution, $styleCode, $cdn);
					$migrations->Log("New favicon path: '$newCdnPath'");
					if (!isset($style['favicon_resolutions']))
					{
						$style['favicon_resolutions'] = [];
					}
					$style['favicon_resolutions'][] = $resolution;
				} catch (\Exception $e) {
					$migrations->Log("Failed to update favicon for '$styleCode': " . $e->getMessage());
					$migrations->Log((string) $e);
				}
			}
			unset($style['favicon']);
		}

		if (isset($style['page_bg_image']))
		{
			$processedUrls = [];

			if (is_array($style['page_bg_image']))
			{
				$urlCount = count($style['page_bg_image']);

				foreach ($style['page_bg_image'] as $offset => $url)
				{
					// If we've got all the sizes we want, or if it's a duplicate file reference to one already processed, skip it.
					if (!isset($backgroundSizes[$offset]) || in_array($url, $processedUrls))
					{
						continue;
					}

					try {
						$cdnPath = getStyleAssetCdnPath($url);
						$migrations->Log("Renaming background image (index #$offset of $urlCount): URL: '$url', CDN Path: '$cdnPath', Size: '$backgroundSizes[$offset]', Style code: '$styleCode'");
						$newCdnPath = renameStyleBackground($cdnPath, $backgroundSizes[$offset], $styleCode, $cdn);
						$migrations->Log("New background path: '$newCdnPath'");
						if (!isset($style['background_resolutions']))
						{
							$style['background_resolutions'] = [];
						}
						$style['background_resolutions'][] = $backgroundSizes[$offset];
						$processedUrls[]                   = $url;
					} catch (\Exception $e) {
						$migrations->Log("Failed to update background image for '$styleCode': " . $e->getMessage());
						$migrations->Log((string) $e);
					}
				}
			} elseif (is_string($style['page_bg_image']) && $style['page_bg_image'] !== '')
			{
				// Handle legacy background image data; single appdata URL as a string
				$url = $style['page_bg_image'];

				try {
					$cdnPath = getStyleAssetCdnPath($url);
					$migrations->Log("Renaming background image (legacy, single-URL): URL: '$url', CDN Path: '$cdnPath', Size: '$backgroundSizes[$offset]', Style code: '$styleCode'");
					$newCdnPath = renameStyleBackground($cdnPath, $backgroundSizes[0], $styleCode, $cdn);
					$migrations->Log("New background path: '$newCdnPath'");
					$style['background_resolutions'] = [$backgroundSizes[0]];
				} catch (\Exception $e) {
					$migrations->Log("Failed to update background image '$cdnPath' for '$styleCode': " . $e->getMessage());
					$migrations->Log((string) $e);
					$migrations->Log("Disabling background for theme code '$styleCode'");
					unset($style['background_resolutions']);
				}

				$processedUrls[] = $url;
			} elseif ($style['page_bg_image'] === '')
			{
				$migrations->Log("Disabling background for theme code '$styleCode'");
				$style['background_disabled'] = true;
			}

			unset($style['page_bg_image']);
		}

		return $style;
	}
}

if (!function_exists('getStyleAssetCdnPath'))
{
	/**
	 * Given a Style's Asset's URL Path,
	 * creates and returns the Asset's CDN filepath.
	 *
	 * @param string $url
	 * @return string
	 * @throws Exception If the URL is invalid
	 */
	function getStyleAssetCdnPath(string $url): string
	{
		$urlPath = parse_url($url, PHP_URL_PATH);
		if (!is_string($urlPath))
		{
			throw new Exception("Theme style has an invalid asset URL '$url'");
		}
		$urlPathArray = array_reverse(explode('/', $urlPath));

		return "$urlPathArray[2]/$urlPathArray[1]/$urlPathArray[0]";
	}
}

if (!function_exists('renameStyleLogo'))
{
	/**
	 * Given a Style's Logo's path,
	 * updates the path to the latest standard if incorrect.
	 *
	 * Returns the new path.
	 *
	 * @param string                             $currentPath
	 * @param string                             $styleCode
	 * @param \Claromentis\Core\CDN\CDNInterface $cdn
	 * @return string
	 * @throws \Claromentis\Core\CDN\FileExistsException If a file already exists with that name.
	 * @throws \Claromentis\Core\CDN\NotFoundException If the file to be renamed could not be found.
	 * @throws \Claromentis\Core\CDN\CDNSystemException
	 */
	function renameStyleLogo(string $currentPath, string $styleCode, \Claromentis\Core\CDN\CDNInterface $cdn): string
	{
		$newPath = "theme/{$styleCode}/logo." . pathinfo($currentPath, PATHINFO_EXTENSION);

		if ($currentPath !== $newPath)
		{
			$cdn->RenameFile($currentPath, $newPath);
		}

		return $newPath;
	}
}

if (!function_exists('renameStyleFavicon'))
{
	/**
	 * Given a Style's Favicon's path,
	 * updates the path to the latest standard if incorrect.
	 *
	 * Returns the new path.
	 *
	 * @param string                             $currentPath
	 * @param string                             $resolution
	 * @param string                             $styleCode
	 * @param \Claromentis\Core\CDN\CDNInterface $cdn
	 * @return string
	 * @throws \Claromentis\Core\CDN\CDNSystemException
	 * @throws \Claromentis\Core\CDN\FileExistsException If a file already exists with that name.
	 * @throws \Claromentis\Core\CDN\NotFoundException If the file to be renamed could not be found.
	 */
	function renameStyleFavicon(string $currentPath, string $resolution, string $styleCode, \Claromentis\Core\CDN\CDNInterface $cdn): string
	{
		$newPath = "theme/{$styleCode}/favicon-$resolution.png";

		if ($currentPath !== $newPath)
		{
			$cdn->RenameFile($currentPath, $newPath);
		}

		return $newPath;
	}
}

if (!function_exists('renameStyleBackground'))
{
	/**
	 * Given a Style's background's path,
	 * updates the path to the latest standard if incorrect.
	 *
	 * Returns the new path.
	 *
	 * @param string                             $currentPath
	 * @param string                             $resolution
	 * @param string                             $styleCode
	 * @param \Claromentis\Core\CDN\CDNInterface $cdn
	 * @return string
	 * @throws \Claromentis\Core\CDN\CDNSystemException
	 * @throws \Claromentis\Core\CDN\FileExistsException If a file already exists with that name.
	 * @throws \Claromentis\Core\CDN\NotFoundException If the file to be renamed could not be found.
	 */
	function renameStyleBackground(string $currentPath, string $resolution, string $styleCode, \Claromentis\Core\CDN\CDNInterface $cdn): string
	{
		$newPath = "theme/{$styleCode}/background-$resolution.png";

		if ($currentPath !== $newPath)
		{
			$cdn->RenameFile($currentPath, $newPath);
		}

		return $newPath;
	}
}

$result = $db->query("SELECT id, style FROM theme_style");

while ($row = $result->fetchArray())
{
	$style = json_decode($row['style'], true);
	if (!is_array($style))
	{
		continue;
	}

	$migrations->Log("Updating Style data for Master Design");
	$style = updateStyleStorageData($style, '_default', $cdn, $migrations);

	$styleString = json_encode($style);

	$db->query("UPDATE theme_style SET style = clob:value WHERE id = int:id", $styleString, $row['id']);
}

$result = $db->query("SELECT id, style, code FROM theme");

while ($row = $result->fetchArray())
{
	$style = json_decode($row['style'], true);
	if (!is_array($style))
	{
		continue;
	}

	$migrations->Log("Updating Style data for Theme {$row['code']}");
	$style = updateStyleStorageData($style, $row['code'], $cdn, $migrations);
	$styleString = json_encode($style);

	$db->query("UPDATE theme SET style = clob:value WHERE id = int:id", $styleString, $row['id']);
}

DB_UPDATE_FILE
);


//===========================================================================================
$migrations->SetVersion('39.03');
