<?php

namespace Planaday\Html\NodeTags\Course\ListShortcode;

use Planaday\Api\ApiException\InvalidResponseException;
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\Entities\Course\CourseController;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\Conditions\InputValueCondition;
use Planaday\Utility\FormBuilder\DataTypes\ArrayType;
use Planaday\Utility\FormBuilder\DataTypes\IntType;
use Planaday\Utility\FormBuilder\DataTypes\StringType;
use Planaday\Utility\FormBuilder\InputFields\BoolInput;
use Planaday\Utility\FormBuilder\InputFields\MultiSelectInput;
use Planaday\Utility\FormBuilder\InputFields\NumberInput;
use Planaday\Utility\FormBuilder\InputFields\RadioInput;
use Planaday\Utility\FormBuilder\InputFields\StringInput;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Structures\CollapsibleGroup;
use Planaday\Utility\FormBuilder\Validators\Required;

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

	protected int $start = 0;
	protected int $end = 3;
	protected int $limit = -1;
	/** @var string[] */
	protected array $labels = [];
	/** @var int[] */
	protected array $templateId = [];
	/** @var int[] */
	protected array $companies = [];
	/** @var string[] */
	protected array $cities = [];
	protected int $showInCompanyCourses = 0;
	protected int $searchBehaviour = 0;
	protected string $noSearchText = "U heeft nog nergens op gezocht.";
	protected string $noResultsText = "Geen resultaten gevonden.";
	protected string $noCoursesText = "Momenteel zijn er geen cursussen gevonden, bel naar ons voor meer informatie.";
	protected bool $includeFullCourses = false;
	protected bool $includePartiallyPassedCourses = false;

	public function __construct(
		protected LocalizationController $translator,
		protected CourseController $controller,
		SettingsLoader $settingsLoader
	) {
		$settingsLoader->reloadData($this, CourseListShortcodeSettingsEnum::class);
	}

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

		$options = [];
		try{
			$templates = $this->controller->getCourseTemplateList();

			foreach ($templates as $template){
				$options[] = [
					"label" => $template->getId() . ' (' . $template->getName() . ')',
					"value" => $template->getId()
				];
			}
		} catch (InvalidResponseException) {}

		usort($options, function($a, $b) {return $a['value'] <=> $b['value'];});

		return ( new CollapsibleGroup() )
			->setIndex( CourseListShortcodeSettingsEnum::class )
			->setHeader( $t("Cursuslijst Inhoud"))
			->setDescription( $t("Stel in welke cursussen getoond worden in deze lijst."))
			->startCollapsed()
			->addContents(
				(new NumberInput())
					->setIndex(CourseListShortcodeSettingsEnum::Start->value)
					->setName($t("Start"))
					->setDescription($t("De start van het tijdvak in maanden vanaf nu (kan negatief)"))
					->setDefaultValue($this->start)
					->setMin(-6)
					->setMax(6)
					->addSetCallback(function ($value) {
						$this->start = $value ?? $this->start;
					})
					->addValidator(new Required($t("Deze waarde is verplicht"))),
				(new NumberInput())
					->setIndex(CourseListShortcodeSettingsEnum::End->value)
					->setName($t("Eind"))
					->setDescription($t("Het einde van het tijdvak in maanden vanaf nu"))
					->setDefaultValue($this->end)
					->setMin(0)
					->setMax(12)
					->addSetCallback(function ($value) {
						$this->end = $value ?? $this->end;
					})
					->addValidator(new Required($t("Deze waarde is verplicht"))),
				(new NumberInput())
					->setIndex(CourseListShortcodeSettingsEnum::Limit->value)
					->setName($t("Limiet"))
					->setDescription($t("Het aantal cursussen dat maximaal getoond wordt in de lijst. -1 = geen limiet."))
					->setDefaultValue($this->limit)
					->setMin(-1)
					->addSetCallback(function ($value) {
						$this->limit = $value ?? $this->limit;
					}),
				$searchBehaviour = (new RadioInput(new IntType()))
					->setIndex(CourseListShortcodeSettingsEnum::SearchBehaviour->value)
					->setName($t("Zoekopdracht gebruiken"))
					->setDescription($t("Wat moet de lijst doen wanneer er een zoekformulier is gebruikt?"))
					->setDefaultValue($this->searchBehaviour)
					->addSetCallback(function ($value) {
						$this->searchBehaviour = $value ?? $this->searchBehaviour;
					})
					->setOptions([
						["value" => 0, "label" => "Niet gebruiken"],
						["value" => 1, "label" => "Filter (De lijst filteren op basis van de zoekopdracht)"],
						["value" => 2, "label" => "Zoek (De instellingen van de lijst overschrijven met de zoekopdracht)"],
					])
					->addValidator(new Required($t("Deze waarde is verplicht"))),
				(new BasicGroup())
					->addConditions(
						( new InputValueCondition($searchBehaviour))->greaterThan()->value(0)
					)->addContents(
						(new StringInput())
							->setIndex(CourseListShortcodeSettingsEnum::NoResultsText->value)
							->setName($t("Geen resultaten tekst"))
							->setDescription($t("Tekst die wordt getoond wanneer er geen resultaten gevonden zijn."))
							->setDefaultValue($this->noResultsText)
							->setPlaceholder($t("Geen resultaten gevonden"))
							->addSetCallback(function ($value) {
								$this->noResultsText = $value ?? $this->noResultsText;
							})
							->addValidator(new Required($t("Deze tekst is verplicht wanneer de lijst zoekresultaten toont"))),
					),
				(new BasicGroup())
					->addConditions(
						( new InputValueCondition($searchBehaviour))->equals()->value(2)
					)->addContents(
						(new StringInput())
							->setIndex(CourseListShortcodeSettingsEnum::NoSearchText->value)
							->setName($t("Geen zoekopdracht tekst"))
							->setDescription($t("Tekst die wordt getoond wanneer er geen zoekopdracht is geweest."))
							->setDefaultValue($this->noSearchText)
							->setPlaceholder($t("U heeft nog nergens op gezocht."))
							->addSetCallback(function ($value) {
								$this->noSearchText = $value ?? $this->noSearchText;
							})
							->addValidator(new Required($t("Deze tekst is verplicht wanneer de lijst zoekresultaten toont"))),
					),
				(new CollapsibleGroup())
					->startCollapsed()
					->setHeader($t("Cursussen filteren"))
					->setDescription($t("Cursussen filteren op basis van zijn eigenschappen."))
					->addContents(
						(new MultiSelectInput(new ArrayType(new StringType())))
							->setIndex(CourseListShortcodeSettingsEnum::Labels->value)
							->setName($t("Labels"))
							->setDescription($t("Toon alleen cursussen met deze labels in de lijst."))
							->setDefaultValue($this->labels)
							->addSetCallback(function ($value) {
								$this->labels = $value ?? $this->labels;
							})
							->setOptions( $this->controller->getUniqueLabelsCourse())
							->allowCustom()
							->setCustomInput(
								(new StringInput())
									->setIndex("custom")
									->setName($t("Ander Label toevoegen"))
									->setDescription($t("Voeg een ander label toe."))
									->setPlaceholder($t("Ander label"))
							),
						(new MultiSelectInput(new ArrayType(new IntType())))
							->setIndex(CourseListShortcodeSettingsEnum::TemplateId->value)
							->setName($t("Template ID"))
							->setDescription($t("Toon alleen cursussen met deze template IDs in de lijst."))
							->setDefaultValue($this->templateId)
							->addSetCallback(function ($value) {
								$this->templateId = $value ?? $this->templateId;
							})
							->setOptions($options)
							->allowCustom()
							->setCustomInput(
								(new NumberInput())
									->setIndex("custom")
									->setName($t("Ander Template ID toevoegen"))
									->setDescription($t("Voeg een ander Template ID toe."))
									->setMin(1)
							),
						(new MultiSelectInput(new ArrayType(new StringType())))
							->setIndex(CourseListShortcodeSettingsEnum::Cities->value)
							->setName($t("Steden"))
							->setDescription($t("Toon alleen cursussen die in deze steden worden gegeven."))
							->setDefaultValue($this->cities)
							->addSetCallback(function ($value) {
								$this->cities = $value ?? $this->cities;
							})
							->setOptions( $this->controller->getUniqueCitiesCourse())
							->allowCustom()
							->setCustomInput(
								(new StringInput())
									->setIndex("custom")
									->setName($t("Andere stad toevoegen"))
									->setDescription($t("Voeg een andere stad toe."))
									->setPlaceholder($t("Andere stad"))
							),
						$showInCompanyCourse = (new RadioInput(new IntType()))
							->setIndex(CourseListShortcodeSettingsEnum::ShowInCompanyCourses->value)
							->setName($t("Toon in-company cursussen"))
							->setDescription("Toon in-company cursussen in de lijst.")
							->setDefaultValue($this->showInCompanyCourses)
							->addSetCallback(function ($value) {
								$this->showInCompanyCourses = $value ?? $this->showInCompanyCourses;
							})
							->setOptions([
								["value" => 0, "label" => "Alleen open cursussen tonen"],
								["value" => 1, "label" => "Alleen in-company cursussen tonen"],
								["value" => 2, "label" => "Alle cursussen tonen"],
							])->addValidator(new Required($t("Deze waarde is verplicht"))),
						(new BasicGroup())
							->addContents(
								(new MultiSelectInput(new ArrayType(new IntType())))
									->setIndex(CourseListShortcodeSettingsEnum::Companies->value)
									->setName($t("Gekoppelde bedrijven"))
									->setDescription($t("Toon alleen cursussen gekoppeld aan deze bedrijven in de lijst."))
									->setDefaultValue($this->companies)
									->addSetCallback(function ($value) {
										$this->companies = $value ?? $this->companies;
									})
									->setOptions([])
									->allowCustom()
									->setCustomInput(
										(new NumberInput())
											->setIndex("custom")
											->setName($t("Bedrijf id toevoegen"))
											->setDescription($t("Voeg een bedrijf id toe."))
											->setMin(1)
									)
							)->addConditions(
								( new InputValueCondition($showInCompanyCourse))->equals()->value(1)
							)->addClasses("pad-subgroup")
					),
				( new StringInput() )
					->setIndex( CourseListShortcodeSettingsEnum::NoCoursesText->value )
					->setName( $t("Geen cursussen text") )
					->setDescription($t("Deze text word getoond als er geen cursussen kunnen worden getoond."))
					->setDefaultValue( $this->noCoursesText )
					->setPlaceholder( $t("Momenteel zijn er geen cursussen gevonden, bel naar ons voor meer informatie.") )
					->addSetCallback( function ( $value ) {
						$this->noCoursesText = $value ?? $this->noCoursesText;
					})
					->addValidator(
						new Required( $t("Dit veld is verplicht"))
					),
				( new BoolInput() )
					->setIndex( CourseListShortcodeSettingsEnum::IncludeFullCourses->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( CourseListShortcodeSettingsEnum::IncludePartiallyPassedCourses->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;
					}),
			);
	}

	/**
	 * @return array{values:mixed[], subGroups:array[], subGroupAliases:string[]}
	 */
	public function getEnumMapping(): array {
		return [
			"values"          => [
				CourseListShortcodeSettingsEnum::Start->value                => &$this->start,
				CourseListShortcodeSettingsEnum::End->value                  => &$this->end,
				CourseListShortcodeSettingsEnum::Limit->value                => &$this->limit,
				CourseListShortcodeSettingsEnum::Labels->value               => &$this->labels,
				CourseListShortcodeSettingsEnum::TemplateId->value           => &$this->templateId,
				CourseListShortcodeSettingsEnum::SearchBehaviour->value      => &$this->searchBehaviour,
				CourseListShortcodeSettingsEnum::NoResultsText->value        => &$this->noResultsText,
				CourseListShortcodeSettingsEnum::NoSearchText->value         => &$this->noSearchText,
				CourseListShortcodeSettingsEnum::Companies->value            => &$this->companies,
				CourseListShortcodeSettingsEnum::ShowInCompanyCourses->value => &$this->showInCompanyCourses,
				CourseListShortcodeSettingsEnum::Cities->value               => &$this->cities,
				CourseListShortcodeSettingsEnum::NoCoursesText->value       => &$this->noCoursesText,
				CourseListShortcodeSettingsEnum::IncludeFullCourses->value   => &$this->includeFullCourses,
				CourseListShortcodeSettingsEnum::IncludePartiallyPassedCourses->value => &$this->includePartiallyPassedCourses,
			],
			"subGroups"       => [],
			"subGroupAliases" => []
		];
	}

	public function getStart(): int {
		$this->logUse(CourseListShortcodeSettingsEnum::Start);
		return $this->start;
	}

	public function getEnd(): int {
		$this->logUse(CourseListShortcodeSettingsEnum::End);
		return $this->end;
	}

	public function getLimit(): int {
		$this->logUse(CourseListShortcodeSettingsEnum::Limit);
		return $this->limit;
	}

	public function getLabels(): array {
		$this->logUse(CourseListShortcodeSettingsEnum::Labels);
		return $this->labels;
	}

	public function getTemplateId(): array {
		$this->logUse(CourseListShortcodeSettingsEnum::TemplateId);
		return $this->templateId;
	}

	public function getCompanies(): array {
		$this->logUse(CourseListShortcodeSettingsEnum::Companies);
		return $this->companies;
	}

	public function getCities(): array {
		$this->logUse(CourseListShortcodeSettingsEnum::Cities);
		return $this->cities;
	}

	public function getShowInCompanyCourses(): int {
		$this->logUse(CourseListShortcodeSettingsEnum::ShowInCompanyCourses);
		return $this->showInCompanyCourses;
	}

	public function getSearchBehaviour(): int {
		$this->logUse(CourseListShortcodeSettingsEnum::SearchBehaviour);
		return $this->searchBehaviour;
	}

	public function getNoSearchText(): string {
		$this->logUse(CourseListShortcodeSettingsEnum::NoSearchText);
		return $this->noSearchText;
	}

	public function getNoResultsText(): string {
		$this->logUse(CourseListShortcodeSettingsEnum::NoResultsText);
		return $this->noResultsText;
	}

	public function getNoCoursesText(): string {
		$this->logUse(CourseListShortcodeSettingsEnum::NoCoursesText);
		return $this->noCoursesText;
	}

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

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