<?php

namespace Planaday\Config\Course\Detail;

use Planaday\Config\BasicEnumMappedSetting;
use Planaday\Config\BasicSettingsLog;
use Planaday\Config\EnumMappedSettings;
use Planaday\Config\FeatureToggles\FeatureToggleSettings;
use Planaday\Config\FormGroupable;
use Planaday\Config\SettingsLoader;
use Planaday\Config\SettingsWithForm;
use Planaday\Config\SettingsWithUsageLog;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Platform\PlatformAbstraction\UrlHandler;
use Planaday\Platform\WordpressConfig\Blocks\WordPressBlock;
use Planaday\Platform\WordpressConfig\ShortcodeLinks\CourseShortcodes;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\Conditions\InputValueCondition;
use Planaday\Utility\FormBuilder\DataTypes\IntType;
use Planaday\Utility\FormBuilder\InputFields\BoolInput;
use Planaday\Utility\FormBuilder\InputFields\SelectionInput;
use Planaday\Utility\FormBuilder\LayoutItems\Text;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Structures\CollapsibleGroup;
use Planaday\Utility\FormBuilder\Structures\QuestionCluster;
use Planaday\Utility\FormBuilder\Validators\Required;
use Planaday\Utility\PluginData;

#[Scoped]
class DetailSettings implements EnumMappedSettings, SettingsWithForm, SettingsWithUsageLog {
	use FormGroupable;
	use BasicEnumMappedSetting;
	use BasicSettingsLog;

	protected bool $showSoobLabel = false;
	protected bool $showCode95Label = false;
	protected bool $showLabels = false;
	protected bool $showDayPartCount = true;
	protected bool $showLevelCourse = false;
	protected bool $showDescriptionDayPart = false;
	protected bool $showAvailability = false;
	protected bool $showStartGuaranteeLabel = false;
	protected bool $showMoneyBackLabel = false;
	protected bool $showFinancialInfo = false;
	protected bool $showPrice = true;
	protected bool $showPriceWithAndWithoutTax = false;
	protected bool $showIcons = false;
	protected bool $showELearningIcon = false;
	protected bool $showDescription = true;
	protected bool $showDayPartList = false;
	protected bool $showLocationDayPart = false;
	protected bool $showELearningDayPart = false;
	protected bool $includeELearningDayParts = false;
	protected bool $showLabelsDayPart = false;
	protected int $selectedDetailPage = 0;
	protected int $overriddenDetailPage = 0;
	protected int $courseNotFoundPage = 0;

	public function __construct(
		protected LocalizationController $translator,
		protected SettingsLoader $settingsDatabase,
		protected UrlHandler $urlHandler,
		protected PluginData $pluginData,
		protected FeatureToggleSettings $featureToggleSettings
	) {
		$this->settingsDatabase->reloadData( $this, DetailOptionsEnum::class );
	}

	protected function createFormGroup(): BasicGroup {
		$t = function ( string $string ) {
			return $this->translator->translate( $string );
		};

		$shortcodeItemsVisible = $this->featureToggleSettings->showShortcodeSettings();

		$detailShortcodePages = array_merge(
			$this->urlHandler->getPagesWithShortCode($this->pluginData->getShortPrefix() . CourseShortcodes::COURSE_OVERVIEW_SHORTCODE),
			$this->urlHandler->getPagesWithBlock($this->pluginData->getFullPrefix() . '/' . WordPressBlock::CourseDetails->value)
		);
		$allPages = $this->urlHandler->getAllPages();

		$detailPageOptions = [];
		$allPageOptions = [];

		foreach ($detailShortcodePages as $page) {
			$detailPageOptions[] = [
				"value" => $page["id"],
				"label" => $page["title"]
			];
		}

		foreach ($allPages as $page) {
			$allPageOptions[] = [
				"value" => $page["id"],
				"label" => $page["title"]
			];
		}

		$form = ( new BasicGroup() )
			->setIndex( DetailOptionsEnum::class )
			->addContents(
				new Text($t('Instellingen voor de detail pagina')),
				$detailPageQuestion = (new SelectionInput(new IntType()))
					->setIndex( DetailOptionsEnum::SELECTED_DETAIL_PAGE->value )
					->setName( $t("Detailpagina"))
					->setDescription( $t("Selecteer de pagina waarop de detailpagina moet worden geladen.") )
					->setDefaultValue( $this->selectedDetailPage )
					->setOptions( [
						[
							"value" => 0,
							"label" => $t("Selecteer een pagina")
						],
						...$detailPageOptions
					])
					->addSetCallback( function ( $value ) {
						$this->selectedDetailPage = $value ?? $this->selectedDetailPage;
					}),
				(new BasicGroup())
					->addConditions(
						(new InputValueCondition($detailPageQuestion))->equals()->value(0)
					)->addContents(
						(new CollapsibleGroup())->startCollapsed()
							->setHeader( $t("Detailpagina overschrijven") )
							->addContents(
								$overriddenDetailPageQuestion = (new SelectionInput(new IntType()))
									->setIndex( DetailOptionsEnum::OVERRIDDEN_DETAIL_PAGE->value )
									->setName( $t("Detailpagina overschrijven"))
									->setDescription( $t("Selecteer de pagina die als detailpagina moet worden behandeld.") )
									->setDefaultValue( $this->overriddenDetailPage )
									->setOptions([
										[
											"value" => 0,
											"label" => $t("Selecteer een pagina")
										],
										...$allPageOptions
									])
									->addSetCallback( function ( $value ) {
										$this->overriddenDetailPage = $value ?? $this->overriddenDetailPage;
									})
									->addValidator(
										(new Required($t('Een detailpagina is verplicht')))->zeroIsInvalid()
											->addCondition(
												(new InputValueCondition($detailPageQuestion))->equals()->value(0)
											)
									),
								(new Text($t("Deze optie is aanwezig voor wanneer de gemaakte detailpagina " .
								             "niet zichtbaar is in de eerdere optie. Wij raden aan om de standaard " .
								             "optie te gebruiken.")))
									->addClasses('pad-warning'),
							)
					),
				(new BasicGroup())
					->addContents(
						$courseNotFoundPageQuestion = (new SelectionInput(new IntType()))
							->setIndex( DetailOptionsEnum::COURSE_NOT_FOUND_PAGE->value )
							->setName( $t("Pagina voor niet gevonden cursussen"))
							->setDescription($t(""))
							->setDefaultValue( $this->courseNotFoundPage )
							->setOptions([
								[
									"value" => 0,
									"label" => $t("Selecteer een pagina")
								],
								...$allPageOptions
							])
							->addSetCallback( function ( $value ) {
								$this->courseNotFoundPage = $value ?? $this->courseNotFoundPage;
							}),
						(new BasicGroup())
							->addConditions(
								(new InputValueCondition($courseNotFoundPageQuestion))->not()->equals()->value(0)
							)->addContents(
								(new Text($t('LET OP: Om door te sturen moet op de detailpagina de ' .
								             '"[padc-course-not-found-redirect]" shortcode aanwezig zijn.')))
									->addClasses('pad-warning'),
							)
					),
			);
		if ($shortcodeItemsVisible) {
			$form->addContents(
				(new QuestionCluster())
					->setName($t("Zichtbare Labels"))
					->setDescription($t("Welke labels moeten zichtbaar zijn bij de cursus"))
					->addContents(
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_SOOB_LABEL->value )
							->setName( $t("SOOB"))
							->setDescription( $t("Toon het SOOB label bij de cursus") )
							->setDefaultValue( $this->showSoobLabel )
							->addSetCallback( function ( $value ) {
								$this->showSoobLabel = $value ?? $this->showSoobLabel;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_CODE_95_LABEL->value )
							->setName( $t("Code 95"))
							->setDescription( $t("Toon het Code 95 label bij de cursus") )
							->setDefaultValue( $this->showCode95Label )
							->addSetCallback( function ( $value ) {
								$this->showCode95Label = $value ?? $this->showCode95Label;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_E_LEARNING_ICON->value )
							->setName( $t("E-learning"))
							->setDescription( $t("Moet er een icoon worden getoond voor e-learning?") )
							->setDefaultValue( $this->showELearningIcon )
							->addSetCallback( function ( $value ) {
								$this->showELearningIcon = $value ?? $this->showELearningIcon;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_LABELS->value )
							->setName( $t("Labels"))
							->setDescription( $t("Toon de labels bij de cursus") )
							->setDefaultValue( $this->showLabels )
							->addSetCallback( function ( $value ) {
								$this->showLabels = $value ?? $this->showLabels;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_DAY_PART_COUNT->value )
							->setName( $t("Dagdeel aantal"))
							->setDescription( $t("Toon het dagdeel aantal bij de cursus") )
							->setDefaultValue( $this->showDayPartCount )
							->addSetCallback( function ( $value ) {
								$this->showDayPartCount = $value ?? $this->showDayPartCount;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_LEVEL_COURSE->value )
							->setName( $t("Niveau cursus"))
							->setDescription( $t("Toon het niveau bij de cursus") )
							->setDefaultValue( $this->showLevelCourse )
							->addSetCallback( function ( $value ) {
								$this->showLevelCourse = $value ?? $this->showLevelCourse;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_AVAILABILITY->value )
							->setName( $t("Beschikbare plaatsen"))
							->setDescription( $t("Toon de beschikbaarheid bij de cursus") )
							->setDefaultValue( $this->showAvailability )
							->addSetCallback( function ( $value ) {
								$this->showAvailability = $value ?? $this->showAvailability;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_START_GUARANTEE_LABEL->value )
							->setName( $t("Start garantie"))
							->setDescription( $t("Toon het start garantie label bij de cursus") )
							->setDefaultValue( $this->showStartGuaranteeLabel )
							->addSetCallback( function ( $value ) {
								$this->showStartGuaranteeLabel = $value ?? $this->showStartGuaranteeLabel;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_MONEY_BACK_LABEL->value )
							->setName( $t("Geld terug garantie"))
							->setDescription( $t("Toon het geld terug label bij de cursus") )
							->setDefaultValue( $this->showMoneyBackLabel )
							->addSetCallback( function ( $value ) {
								$this->showMoneyBackLabel = $value ?? $this->showMoneyBackLabel;
							}),
						(new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_FINANCIAL_INFO->value )
							->setName($t("Financiële toelichting (Betalingsinstellingen)"))
							->setDescription($t("Toon de financiële informatie bij de cursus"))
							->setDefaultValue( $this->showFinancialInfo )
							->addSetCallback( function ( $value ) {
								$this->showFinancialInfo = $value ?? $this->showFinancialInfo;
							}),
						$showPriceQuestion = (new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_PRICE->value )
							->setName( $t("Prijs"))
							->setDescription( $t("Toon de prijs bij de cursus") )
							->setDefaultValue( $this->showPrice )
							->addSetCallback( function ( $value ) {
								$this->showPrice = $value ?? $this->showPrice;
							}),
						(new BasicGroup())
							->addConditions(
								(new InputValueCondition($showPriceQuestion))->equals()->value(true)
							)->addContents(
								(new BoolInput())
									->setIndex( DetailOptionsEnum::SHOW_PRICE_WITH_AND_WITHOUT_TAX->value )
									->setName( $t("Prijs inclusief en exclusief belasting"))
									->setDescription( $t("Toon de prijs inclusief en exclusief belasting bij de cursus") )
									->setDefaultValue( $this->showPriceWithAndWithoutTax )
									->addSetCallback( function ( $value ) {
										$this->showPriceWithAndWithoutTax = $value ?? $this->showPriceWithAndWithoutTax;
									})
							)
					),
				(new BoolInput())
					->setIndex( DetailOptionsEnum::SHOW_ICONS->value)
					->setName( $t("Toon icoon"))
					->setDescription( $t("Toon iconen bij de labels") )
					->setDefaultValue( $this->showIcons )
					->addSetCallback( function ( $value ) {
						$this->showIcons = $value ?? $this->showIcons;
					}),
				(new BoolInput())
					->setIndex( DetailOptionsEnum::SHOW_DESCRIPTION->value )
					->setName( $t("Omschrijving"))
					->setDescription( $t("Moet er een omschrijving worden getoond?") )
					->setDefaultValue( $this->showDescription )
					->addSetCallback( function ( $value ) {
						$this->showDescription = $value ?? $this->showDescription;
					}),
				(new CollapsibleGroup())
					->setHeader( $t("Dagdelen") )
					->setDescription($t("Instellingen voor de dagdelen lijst op de detailpagina."))
					->addContents(
						$showDayPartListQuestion = (new BoolInput())
							->setIndex( DetailOptionsEnum::SHOW_DAY_PART_LIST->value )
							->setName( $t("Toon dagdeel lijst"))
							->setDescription( $t("Toon de dagdeel lijst bij de cursus") )
							->setDefaultValue( $this->showDayPartList )
							->addSetCallback( function ( $value ) {
								$this->showDayPartList = $value ?? $this->showDayPartList;
							}),
						(new BasicGroup())
							->addConditions(
								(new InputValueCondition($showDayPartListQuestion))->equals()->value(true)
							)->addContents(
								(new BoolInput())
									->setIndex( DetailOptionsEnum::SHOW_LOCATION_DAY_PART->value )
									->setName( $t("Toon locatie dagdeel"))
									->setDescription( $t("Toon de locatie bij het dagdeel") )
									->setDefaultValue( $this->showLocationDayPart )
									->addSetCallback( function ( $value ) {
										$this->showLocationDayPart = $value ?? $this->showLocationDayPart;
									}),
								(new BoolInput())
									->setIndex( DetailOptionsEnum::SHOW_E_LEARNING_DAY_PART->value )
									->setName( $t("Toon e-learning label dagdeel"))
									->setDescription( $t("Toon een e-learning label bij het dagdeel als deze dit heeft") )
									->setDefaultValue( $this->showELearningDayPart )
									->addSetCallback( function ( $value ) {
										$this->showELearningDayPart = $value ?? $this->showELearningDayPart;
									}),
								(new BoolInput())
									->setIndex( DetailOptionsEnum::SHOW_DESCRIPTION_DAY_PART->value )
									->setName( $t("Toon omschrijving dagdeel"))
									->setDescription( $t("Toon de omschrijving bij het dagdeel bij de cursus") )
									->setDefaultValue( $this->showDescriptionDayPart )
									->addSetCallback( function ( $value ) {
										$this->showDescriptionDayPart = $value ?? $this->showDescriptionDayPart;
									}),
								(new BoolInput())
									->setIndex( DetailOptionsEnum::INCLUDE_E_LEARNING_DAY_PARTS->value )
									->setName( $t("Toon e-learning dagdelen"))
									->setDescription( $t("Toon e-learning dagdelen in de lijst met dagdelen") )
									->setDefaultValue( $this->includeELearningDayParts )
									->addSetCallback( function ( $value ) {
										$this->includeELearningDayParts = $value ?? $this->includeELearningDayParts;
									}),
								(new BoolInput())
									->setIndex( DetailOptionsEnum::SHOW_LABELS_DAY_PART->value )
									->setName( $t("Labels dagdelen"))
									->setDescription( $t("Moeten er labels van dagdelen worden getoond?") )
									->setDefaultValue( $this->showLabelsDayPart )
									->addSetCallback( function ( $value ) {
										$this->showLabelsDayPart = $value ?? $this->showLabelsDayPart;
									})
							)
					)->addClasses("pad-grouping"),
			);
		}

		$detailPageQuestion->addValidator(
			(new Required($t('Een detailpagina is verplicht')))->zeroIsInvalid()
				->addCondition(
					(new InputValueCondition($overriddenDetailPageQuestion))->equals()->value(0)
				)
		);

		return $form;
	}

	/**
	 * @return array{values:mixed[], subGroups:array[], subGroupAliases:string[]}
	 */
	public function getEnumMapping(): array {
		return [
			"values"          => [
				DetailOptionsEnum::SHOW_SOOB_LABEL->value => &$this->showSoobLabel,
				DetailOptionsEnum::SHOW_CODE_95_LABEL->value => &$this->showCode95Label,
				DetailOptionsEnum::SHOW_LABELS->value => &$this->showLabels,
				DetailOptionsEnum::SHOW_DAY_PART_COUNT->value => &$this->showDayPartCount,
				DetailOptionsEnum::SHOW_DAY_PART_LIST->value => &$this->showDayPartList,
				DetailOptionsEnum::SHOW_LOCATION_DAY_PART->value => &$this->showLocationDayPart,
				DetailOptionsEnum::SHOW_E_LEARNING_DAY_PART->value => &$this->showELearningDayPart,
				DetailOptionsEnum::SHOW_LEVEL_COURSE->value => &$this->showLevelCourse,
				DetailOptionsEnum::SHOW_DESCRIPTION_DAY_PART->value => &$this->showDescriptionDayPart,
				DetailOptionsEnum::SHOW_AVAILABILITY->value => &$this->showAvailability,
				DetailOptionsEnum::SHOW_START_GUARANTEE_LABEL->value => &$this->showStartGuaranteeLabel,
				DetailOptionsEnum::SHOW_MONEY_BACK_LABEL->value => &$this->showMoneyBackLabel,
				DetailOptionsEnum::SHOW_FINANCIAL_INFO->value => &$this->showFinancialInfo,
				DetailOptionsEnum::SHOW_PRICE->value => &$this->showPrice,
				DetailOptionsEnum::SHOW_PRICE_WITH_AND_WITHOUT_TAX->value => &$this->showPriceWithAndWithoutTax,
				DetailOptionsEnum::SHOW_ICONS->value => &$this->showIcons,
				DetailOptionsEnum::INCLUDE_E_LEARNING_DAY_PARTS->value => &$this->includeELearningDayParts,
				DetailOptionsEnum::SHOW_E_LEARNING_ICON->value => &$this->showELearningIcon,
				DetailOptionsEnum::SHOW_DESCRIPTION->value => &$this->showDescription,
				DetailOptionsEnum::SHOW_LABELS_DAY_PART->value => &$this->showLabelsDayPart,
				DetailOptionsEnum::SELECTED_DETAIL_PAGE->value => &$this->selectedDetailPage,
				DetailOptionsEnum::OVERRIDDEN_DETAIL_PAGE->value => &$this->overriddenDetailPage,
				DetailOptionsEnum::COURSE_NOT_FOUND_PAGE->value => &$this->courseNotFoundPage,
			],
			"subGroups"       => [],
			"subGroupAliases" => []
		];
	}

	public function isShowSoobLabel(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_SOOB_LABEL);
		return $this->showSoobLabel;
	}

	public function isShowCode95Label(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_CODE_95_LABEL);
		return $this->showCode95Label;
	}

	public function isShowLabels(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_LABELS);
		return $this->showLabels;
	}

	public function isShowDayPartCount(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_DAY_PART_COUNT);
		return $this->showDayPartCount;
	}

	public function isShowDayPartList(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_DAY_PART_LIST);
		return $this->showDayPartList;
	}

	public function isShowLocationDayPart(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_LOCATION_DAY_PART);
		return $this->showLocationDayPart;
	}

	public function isShowELearningDayPart(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_E_LEARNING_DAY_PART);
		return $this->showELearningDayPart;
	}

	public function isShowLevelCourse(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_LEVEL_COURSE);
		return $this->showLevelCourse;
	}

	public function isShowDescriptionDayPart(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_DESCRIPTION_DAY_PART);
		return $this->showDescriptionDayPart;
	}

	public function isShowAvailability(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_AVAILABILITY);
		return $this->showAvailability;
	}

	public function isShowStartGuaranteeLabel(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_START_GUARANTEE_LABEL);
		return $this->showStartGuaranteeLabel;
	}

	public function isShowMoneyBackLabel(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_MONEY_BACK_LABEL);
		return $this->showMoneyBackLabel;
	}

	public function isShowFinancialInfo(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_FINANCIAL_INFO);
		return $this->showFinancialInfo;
	}

	public function isShowPrice(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_PRICE);
		return $this->showPrice;
	}

	public function isShowPriceWithAndWithoutTax(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_PRICE_WITH_AND_WITHOUT_TAX);
		return $this->showPriceWithAndWithoutTax;
	}

	public function isShowIcons(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_ICONS);
		return $this->showIcons;
	}

	public function isIncludeELearningDayParts(): bool {
		$this->logUse(DetailOptionsEnum::INCLUDE_E_LEARNING_DAY_PARTS);
		return $this->includeELearningDayParts;
	}

	public function isShowELearningIcon(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_E_LEARNING_ICON);
		return $this->showELearningIcon;
	}

	public function isShowDescription(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_DESCRIPTION);
		return $this->showDescription;
	}

	public function isShowLabelsDayPart(): bool {
		$this->logUse(DetailOptionsEnum::SHOW_LABELS_DAY_PART);
		return $this->showLabelsDayPart;
	}

	public function getSelectedDetailPage(): int {
		$this->logUse(DetailOptionsEnum::SELECTED_DETAIL_PAGE);
		return $this->selectedDetailPage;
	}

	public function getOverriddenDetailPage(): int {
		$this->logUse(DetailOptionsEnum::OVERRIDDEN_DETAIL_PAGE);
		return $this->overriddenDetailPage;
	}

	public function getCourseNotFoundPage(): int {
		$this->logUse(DetailOptionsEnum::COURSE_NOT_FOUND_PAGE);
		return $this->courseNotFoundPage;
	}
}