<?php

namespace Planaday\Html\NodeTags\Course;

use Planaday\Config\BasicEnumMappedSetting;
use Planaday\Config\EnumMappedSettings;
use Planaday\Config\FormGroupable;
use Planaday\Config\SettingsLoader;
use Planaday\Config\SettingsWithForm;
use Planaday\Entities\Course\CourseDatabase;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\Conditions\InputValueCondition;
use Planaday\Utility\FormBuilder\DataTypes\IntType;
use Planaday\Utility\FormBuilder\InputFields\NumberInput;
use Planaday\Utility\FormBuilder\InputFields\SelectionInput;
use Planaday\Utility\FormBuilder\InputFields\StringInput;
use Planaday\Utility\FormBuilder\LayoutItems\Text;
use Planaday\Utility\FormBuilder\Structure;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Structures\CollapsibleGroup;
use Planaday\Utility\FormBuilder\Validators\Required;

#[Scoped]
class InjectionSettings implements EnumMappedSettings, SettingsWithForm {
	use FormGroupable;
	use BasicEnumMappedSetting;

	protected int $selectedCourseId = 0;
	protected string $noSelectedCourseText = "U heeft geen cursus geselecteerd.";
	protected string $courseNotFoundText = "Deze cursus is niet gevonden.";
	protected string $apiErrorText = "Er is een fout opgetreden bij het ophalen van de cursus.";

	public function __construct(
		protected LocalizationController $translator,
		protected CourseDatabase $database,
		SettingsLoader $settingsLoader
	) {
		$settingsLoader->reloadData($this, InjectionSettingsEnum::class);
	}

	protected function createFormGroup(): Structure {
		$t = function ( string $string ) {return $this->translator->translate( $string );};
		$allKnownCourses = $this->database->getAll();

		$options = [];
		foreach ($allKnownCourses as $course){
			$options[] = [
				"value" => $course->getId(),
				"label" => $course->getId() . " (" . $course->getName() . ")"
			];
		}

		return (new CollapsibleGroup())
			->startCollapsed()
			->setIndex(InjectionSettingsEnum::class)
			->setHeader($t( "Cursus selecteren"))
			->setDescription($t("Stel in voor welke cursus de informatie weergeven moet worden."))
			->addContents(
				( new BasicGroup() )
					->addContents(
						$selectedCourse = ( new SelectionInput(new IntType()) )
							->setIndex(InjectionSettingsEnum::SelectedCourseId->value)
							->setName($t("Cursus"))
							->setDescription($t("Welke cursus moet worden weergegeven?"))
							->setDefaultValue($this->selectedCourseId)
							->setAllowCustom(true)
							->setCustomInput(
								(new NumberInput(new IntType()))
									->setIndex("custom")
									->setName($t("Ander Cursus ID"))
									->setDescription($t("Voeg een ander cursus id toe."))
									->setDefaultValue(0)
									->setMin(1)
							)
							->addSetCallback(function ($value) {
								$this->selectedCourseId = $value ?? $this->selectedCourseId;
							})->setOptions([
								["value" => 0, "label" => $t("Bepaal automatisch")],
								...$options,
							]),
						( new BasicGroup() )
							->addConditions(
								(new InputValueCondition($selectedCourse))->equals()->value(0)
							)->addContents(
								(new Text($t("LET OP: Automatische bepaling van de cursus werkt alleen wanneer dit" .
								             " block wordt gebruikt op een detailpagina.")))
									->addClasses("pad-warning"),
								(new StringInput())
									->setIndex(InjectionSettingsEnum::NoCourseSelectedText->value)
									->setName($t("Geen cursus geselecteerd tekst"))
									->setDescription($t("Deze tekst wordt getoond wanneer er geen cursus is geselecteerd."))
									->setDefaultValue($this->noSelectedCourseText)
									->setPlaceholder($t("U heeft geen cursus geselecteerd."))
									->addSetCallback(function ($value) {
										$this->noSelectedCourseText = $value ?? $this->noSelectedCourseText;
									})->addValidator(
										new Required($t("Deze tekst is verplicht wanneer de cursus automatisch wordt bepaald"))
									)
							)->addClasses("pad-subgroup"),
						( new StringInput() )
							->setIndex(InjectionSettingsEnum::CourseNotFoundText->value)
							->setName($t("Cursus niet gevonden tekst"))
							->setDescription($t("Deze tekst wordt getoond wanneer de cursus niet gevonden wordt."))
							->setDefaultValue($this->courseNotFoundText)
							->setPlaceholder($t("Deze cursus is niet gevonden."))
							->addSetCallback(function ($value) {
								$this->courseNotFoundText = $value ?? $this->courseNotFoundText;
							})->addValidator(
								new Required($t("Deze tekst is verplicht wanneer de cursus op id gezocht wordt"))
							),
						( new StringInput() )
							->setIndex(InjectionSettingsEnum::ApiErrorText->value)
							->setName($t("API fout tekst"))
							->setDescription($t("Deze tekst wordt getoond wanneer er een fout opgetreden is bij het ophalen van de cursus."))
							->setDefaultValue($this->apiErrorText)
							->setPlaceholder($t("Er is een fout opgetreden bij het ophalen van de cursus."))
							->addSetCallback(function ($value) {
								$this->apiErrorText = $value ?? $this->apiErrorText;
							})->addValidator(
								new Required($t("Deze tekst is verplicht wanneer de cursus op id gezocht wordt"))
							)
					)
			);
	}

	/**
	 * @return array{values:mixed[], subGroups:array[], subGroupAliases:string[]}
	 */
	public function getEnumMapping(): array {
		return [
			"values" => [
				InjectionSettingsEnum::SelectedCourseId->value => &$this->selectedCourseId,
				InjectionSettingsEnum::NoCourseSelectedText->value => &$this->noSelectedCourseText,
				InjectionSettingsEnum::CourseNotFoundText->value => &$this->courseNotFoundText,
				InjectionSettingsEnum::ApiErrorText->value => &$this->apiErrorText,
			],
			"subGroups" => [],
			"subGroupAliases" => []
		];
	}

	public function getSelectedCourseId(): int {
		return $this->selectedCourseId;
	}

	public function getNoSelectedCourseText(): string {
		return $this->noSelectedCourseText;
	}

	public function getCourseNotFoundText(): string {
		return $this->courseNotFoundText;
	}

	public function getApiErrorText(): string {
		return $this->apiErrorText;
	}
}