<?php

namespace Planaday\Config\Course\Overview;

use Planaday\Config\BasicEnumMappedSetting;
use Planaday\Config\BasicSettingsLog;
use Planaday\Config\EnumMappedSettings;
use Planaday\Config\FormGroupable;
use Planaday\Config\SettingsLoader;
use Planaday\Config\SettingsWithForm;
use Planaday\Config\SettingsWithUsageLog;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\Conditions\InputValueCondition;
use Planaday\Utility\FormBuilder\InputFields\BoolInput;
use Planaday\Utility\FormBuilder\InputFields\NumberInput;
use Planaday\Utility\FormBuilder\InputFields\StringInput;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Structures\CollapsibleGroup;
use Planaday\Utility\FormBuilder\Structures\QuestionCluster;
use Planaday\Utility\FormBuilder\Validators\Required;

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

	protected bool $showCode95Icon = false;
	protected bool $showSoobIcon = false;
	protected bool $showELearningIcon = false;
	protected bool $showMoneyBackNotice = false;
	protected bool $showStartGuaranteeNotice = false;
	protected bool $showFinancialInfo = false;
	protected bool $showPrice = false;
	protected bool $showDayPartCount = false;
	protected bool $showLabels = false;
	protected bool $showFirstLocation = false;
	protected bool $showCourseButton = true;
	protected string $courseButtonText = "Bekijk cursus";
	protected bool $showDayPartList = false;
	protected bool $showLocationDayPart = false;
	protected bool $showLabelsDayPart = false;
	protected string $noCourseText = "Momenteel zijn er geen cursussen gevonden, bel naar ons voor meer informatie.";
	protected bool $includeFullCourses = false;
	protected bool $includePartiallyPassedCourses = false;
	protected bool $showDescription = true;
	protected int $maxLengthDescription = 200;
	protected bool $showAvailability = false;

	public function __construct(
		protected LocalizationController $translator,
		protected SettingsLoader $settingsDatabase
	) {
		$this->settingsDatabase->reloadData( $this, OverviewOptionsEnum::class );
	}

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

		return ( new BasicGroup() )
			->setIndex( OverviewOptionsEnum::class )
			->addContents(
				(new QuestionCluster())
					->setName( $t('Overzicht Eigenschappen') )
					->setDescription( $t("Welke eigenschappen moeten worden getoond?"))
					->addContents(
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_CODE_95_ICON->value )
							->setName( $t("Code 95 icoon") )
							->setDescription( $t("Moet er een icoon worden getoond voor de code 95?") )
							->setDefaultValue( $this->showCode95Icon )
							->addSetCallback( function ( $value ) {
								$this->showCode95Icon = $value ?? $this->showCode95Icon;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_SOOB_ICON->value )
							->setName( $t("SOOB icoon") )
							->setDescription( $t("Moet er een icoon worden getoond voor Soob?") )
							->setDefaultValue( $this->showSoobIcon )
							->addSetCallback( function ( $value ) {
								$this->showSoobIcon = $value ?? $this->showSoobIcon;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_E_LEARNING_ICON->value )
							->setName( $t("E-learning icoon") )
							->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( OverviewOptionsEnum::SHOW_MONEY_BACK_NOTICE->value )
							->setName( $t("Geld terug garantie") )
							->setDescription( $t("Moet er een notitie worden getoond voor de geld terug garantie?") )
							->setDefaultValue( $this->showMoneyBackNotice )
							->addSetCallback( function ( $value ) {
								$this->showMoneyBackNotice = $value ?? $this->showMoneyBackNotice;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_START_GUARANTEE_NOTICE->value )
							->setName( $t("Startgarantie") )
							->setDescription( $t("Moet er een notitie worden getoond voor start garantie?") )
							->setDefaultValue( $this->showStartGuaranteeNotice )
							->addSetCallback( function ( $value ) {
								$this->showStartGuaranteeNotice = $value ?? $this->showStartGuaranteeNotice;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_FINANCIAL_INFO->value )
							->setName($t("Financiële toelichting (Betalingsinstellingen)"))
							->setDescription($t("Moet er financiële informatie worden getoond?"))
							->setDefaultValue($this->showFinancialInfo)
							->addSetCallback( function ( $value ) {
								$this->showFinancialInfo = $value ?? $this->showFinancialInfo;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_PRICE->value )
							->setName( $t("Prijs") )
							->setDescription( $t("Moet er een prijs worden getoond?") )
							->setDefaultValue( $this->showPrice )
							->addSetCallback( function ( $value ) {
								$this->showPrice = $value ?? $this->showPrice;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_DAY_PART_COUNT->value )
							->setName( $t("Aantal dagdelen") )
							->setDescription( $t("Moet het aantal dagdelen worden getoond?") )
							->setDefaultValue( $this->showDayPartCount )
							->addSetCallback( function ( $value ) {
								$this->showDayPartCount = $value ?? $this->showDayPartCount;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_AVAILABILITY->value )
							->setName( $t("Beschikbare plaatsen") )
							->setDescription( $t("Moet het aantal beschikbare plaatsen worden getoond?") )
							->setDefaultValue( $this->showAvailability )
							->addSetCallback( function ( $value ) {
								$this->showAvailability = $value ?? $this->showAvailability;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_LABELS->value )
							->setName( $t("Labels") )
							->setDescription( $t("Moeten de labels worden getoond?") )
							->setDefaultValue( $this->showLabels )
							->addSetCallback( function ( $value ) {
								$this->showLabels = $value ?? $this->showLabels;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_FIRST_LOCATION->value )
							->setName( $t("Eerste locatie") )
							->setDescription( $t("Moet de eerste locatie worden getoond?") )
							->setDefaultValue( $this->showFirstLocation )
							->addSetCallback( function ( $value ) {
								$this->showFirstLocation = $value ?? $this->showFirstLocation;
							})
					),
				$showButtonQuestion = ( new BoolInput() )
					->setIndex( OverviewOptionsEnum::SHOW_COURSE_BUTTON->value )
					->setName( $t("Cursus knop") )
					->setDescription( $t("Moet er een detailknop worden getoond voor de cursus?") )
					->setDefaultValue( $this->showCourseButton )
					->addSetCallback( function ( $value ) {
						$this->showCourseButton = $value ?? $this->showCourseButton;
					}),
				( new BasicGroup() )
					->addConditions(
						( new InputValueCondition( $showButtonQuestion ) )->equals()->value(true)
					)->addContents(
						( new StringInput() )
							->setIndex( OverviewOptionsEnum::COURSE_BUTTON_TEXT->value )
							->setName( $t("Cursus knop tekst") )
							->setDescription($t("Welke tekst moet er op de detailknop voor de cursus worden getoond?"))
							->setDefaultValue( $this->courseButtonText )
							->setPlaceholder( $t("Bekijk cursus") )
							->addSetCallback( function ( $value ) {
								$this->courseButtonText = $value ?? $this->courseButtonText;
							})
							->addValidator(
								new Required( $t("Dit veld is verplicht"))
							)
					)->addClasses("pad-subgroup"),
				$showDescriptionQuestion = ( new BoolInput() )
					->setIndex( OverviewOptionsEnum::SHOW_DESCRIPTION->value )
					->setName( $t("Omschrijving") )
					->setDescription( $t("Moet de omschrijving van een cursus worden getoond?") )
					->setDefaultValue( $this->showDescription )
					->addSetCallback( function ( $value ) {
						$this->showDescription = $value ?? $this->showDescription;
					}),
				( new BasicGroup() )
					->addConditions(
						( new InputValueCondition( $showDescriptionQuestion ) )->equals()->value(true)
					)->addContents(
						(new NumberInput())
							->setIndex( OverviewOptionsEnum::MAX_LENGTH_DESCRIPTION->value )
							->setName( $t("Maximale lengte beschrijving") )
							->setDescription($t("Na hoeveel karakters moet de omschrijving worden afgekapt?"))
							->setDefaultValue( $this->maxLengthDescription )
							->setMin( 1 )
							->addSetCallback( function ( $value ) {
								$this->maxLengthDescription = $value ?? $this->maxLengthDescription;
							})
							->addValidator(
								new Required( $t("Dit veld is verplicht"))
							)
					)->addClasses("pad-subgroup"),
				( new CollapsibleGroup() )
					->setHeader($t("Dagdelen lijst"))
					->setDescription($t("Instellingen voor de lijst met dagdelen bij een cursus in de overzichten."))
					->addContents(
						$showDayPartListQuestion = ( new BoolInput() )
							->setIndex( OverviewOptionsEnum::SHOW_DAY_PART_LIST->value )
							->setName( $t("Lijst dagdelen") )
							->setDescription( $t("Moet er een lijst met dagdelen worden getoond?") )
							->setDefaultValue( $this->showDayPartList )
							->addSetCallback( function ( $value ) {
								$this->showDayPartList = $value ?? $this->showDayPartList;
							}),
						( new BasicGroup() )
							->addConditions(
								( new InputValueCondition( $showDayPartListQuestion ) )->equals()->value(true)
							)->addContents(
								( new BoolInput() )
									->setIndex( OverviewOptionsEnum::SHOW_LOCATION_DAY_PART->value )
									->setName( $t("Locatie dagdelen") )
									->setDescription( $t("Moeten de locaties van de dagdelen worden getoond?") )
									->setDefaultValue( $this->showLocationDayPart )
									->addSetCallback( function ( $value ) {
										$this->showLocationDayPart = $value ?? $this->showLocationDayPart;
									}),
								( new BoolInput() )
									->setIndex( OverviewOptionsEnum::SHOW_LABELS_DAY_PART->value )
									->setName( $t("Labels dagdelen") )
									->setDescription( $t("Moeten de labels van de dagdelen worden getoond?") )
									->setDefaultValue( $this->showLabelsDayPart )
									->addSetCallback( function ( $value ) {
										$this->showLabelsDayPart = $value ?? $this->showLabelsDayPart;
									})
							)
					),
				( new CollapsibleGroup() )
					->setHeader($t("Weergeven cursussen"))
					->setDescription($t("Welke cursussen moeten worden getoond in de overzichten?"))
					->addContents(
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::INCLUDE_FULL_COURSES->value )
							->setName( $t("Inclusief volle cursussen") )
							->setDescription( $t("Moeten volle cursussen worden weergeven?") )
							->setDefaultValue( $this->includeFullCourses )
							->addSetCallback( function ( $value ) {
								$this->includeFullCourses = $value ?? $this->includeFullCourses;
							}),
						( new BoolInput() )
							->setIndex( OverviewOptionsEnum::INCLUDE_PARTIALLY_PASSED_COURSES->value )
							->setName( $t("Inclusief gestarte cursussen") )
							->setDescription( $t("Moeten cursussen die al zijn gestart worden weergeven? (ten opzichte van de geselecteerde startdatum)") )
							->setDefaultValue( $this->includePartiallyPassedCourses )
							->addSetCallback( function ( $value ) {
								$this->includePartiallyPassedCourses = $value ?? $this->includePartiallyPassedCourses;
							}),
						( new StringInput() )
							->setIndex( OverviewOptionsEnum::NO_COURSE_TEXT->value )
							->setName( $t("Geen cursussen text") )
							->setDescription($t("Deze text word getoond als er geen cursussen kunnen worden getoond."))
							->setDefaultValue( $this->noCourseText )
							->setPlaceholder( $t("Momenteel zijn er geen cursussen gevonden, bel naar ons voor meer informatie.") )
							->addSetCallback( function ( $value ) {
								$this->noCourseText = $value ?? $this->noCourseText;
							})
							->addValidator(
								new Required( $t("Dit veld is verplicht"))
							),
					),
			);
	}

	/**
	 * @return array{values:mixed[], subGroups:array[], subGroupAliases:string[]}
	 */
	public function getEnumMapping(): array {
		return [
			"values"          => [
				OverviewOptionsEnum::SHOW_CODE_95_ICON->value => &$this->showCode95Icon,
				OverviewOptionsEnum::SHOW_SOOB_ICON->value => &$this->showSoobIcon,
				OverviewOptionsEnum::SHOW_E_LEARNING_ICON->value => &$this->showELearningIcon,
				OverviewOptionsEnum::SHOW_MONEY_BACK_NOTICE->value => &$this->showMoneyBackNotice,
				OverviewOptionsEnum::SHOW_START_GUARANTEE_NOTICE->value => &$this->showStartGuaranteeNotice,
				OverviewOptionsEnum::SHOW_FINANCIAL_INFO->value => &$this->showFinancialInfo,
				OverviewOptionsEnum::SHOW_PRICE->value => &$this->showPrice,
				OverviewOptionsEnum::SHOW_DAY_PART_COUNT->value => &$this->showDayPartCount,
				OverviewOptionsEnum::SHOW_LABELS->value => &$this->showLabels,
				OverviewOptionsEnum::SHOW_FIRST_LOCATION->value => &$this->showFirstLocation,
				OverviewOptionsEnum::SHOW_COURSE_BUTTON->value => &$this->showCourseButton,
				OverviewOptionsEnum::COURSE_BUTTON_TEXT->value => &$this->courseButtonText,
				OverviewOptionsEnum::SHOW_DAY_PART_LIST->value => &$this->showDayPartList,
				OverviewOptionsEnum::SHOW_LOCATION_DAY_PART->value => &$this->showLocationDayPart,
				OverviewOptionsEnum::SHOW_LABELS_DAY_PART->value => &$this->showLabelsDayPart,
				OverviewOptionsEnum::NO_COURSE_TEXT->value => &$this->noCourseText,
				OverviewOptionsEnum::INCLUDE_FULL_COURSES->value => &$this->includeFullCourses,
				OverviewOptionsEnum::INCLUDE_PARTIALLY_PASSED_COURSES->value => &$this->includePartiallyPassedCourses,
				OverviewOptionsEnum::SHOW_DESCRIPTION->value => &$this->showDescription,
				OverviewOptionsEnum::MAX_LENGTH_DESCRIPTION->value => &$this->maxLengthDescription,
				OverviewOptionsEnum::SHOW_AVAILABILITY->value => &$this->showAvailability,
			],
			"subGroups"       => [],
			"subGroupAliases" => []
		];
	}

	public function isShowCode95Icon(): bool {
		$this->logUse(OverviewOptionsEnum::SHOW_CODE_95_ICON);
		return $this->showCode95Icon;
	}

	public function isShowSoobIcon(): bool {
		$this->logUse(OverviewOptionsEnum::SHOW_SOOB_ICON);
		return $this->showSoobIcon;
	}

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

	public function isShowMoneyBackNotice(): bool {
		$this->logUse(OverviewOptionsEnum::SHOW_MONEY_BACK_NOTICE);
		return $this->showMoneyBackNotice;
	}

	public function isShowStartGuaranteeNotice(): bool {
		$this->logUse(OverviewOptionsEnum::SHOW_START_GUARANTEE_NOTICE);
		return $this->showStartGuaranteeNotice;
	}

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

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

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

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

	public function isShowFirstLocation(): bool {
		$this->logUse(OverviewOptionsEnum::SHOW_FIRST_LOCATION);
		return $this->showFirstLocation;
	}

	public function isShowCourseButton(): bool {
		$this->logUse(OverviewOptionsEnum::SHOW_COURSE_BUTTON);
		return $this->showCourseButton;
	}

	public function getCourseButtonText(): string {
		$this->logUse(OverviewOptionsEnum::COURSE_BUTTON_TEXT);
		return $this->courseButtonText;
	}

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

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

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

	public function getNoCourseText(): string {
		$this->logUse(OverviewOptionsEnum::NO_COURSE_TEXT);
		return $this->noCourseText;
	}

	public function isIncludeFullCourses(): bool {
		$this->logUse(OverviewOptionsEnum::INCLUDE_FULL_COURSES);
		return $this->includeFullCourses;
	}

	public function isIncludePartiallyPassedCourses(): bool {
		$this->logUse(OverviewOptionsEnum::INCLUDE_PARTIALLY_PASSED_COURSES);
		return $this->includePartiallyPassedCourses;
	}

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

	public function getMaxLengthDescription(): int {
		$this->logUse(OverviewOptionsEnum::MAX_LENGTH_DESCRIPTION);
		return $this->maxLengthDescription;
	}

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