<?php

namespace Planaday\Html\NodeTags\Course\Search;

use Planaday\Config\FeatureToggles\FeatureToggleSettings;
use Planaday\Entities\Course\CourseController;
use Planaday\Entities\Course\PostRequest\CourseSearchFieldEnum;
use Planaday\Entities\Location\LocationController;
use Planaday\Entities\PostEntities;
use Planaday\Html\Nodes\NodeData;
use Planaday\Html\NodeTags\Feature;
use Planaday\Html\NodeTags\Tag;
use Planaday\Html\NodeTags\TemplateOnlyTag;
use Planaday\Html\Parsers\NodeParsers\TagMarkers\RefreshUniqueId;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Platform\PlatformAbstraction\UrlHandler;
use Planaday\Utility\DependencyInjection\Attributes\Transient;
use Planaday\Utility\FormBuilder\DataTypes\ArrayType;
use Planaday\Utility\FormBuilder\DataTypes\IntType;
use Planaday\Utility\FormBuilder\DataTypes\StringType;
use Planaday\Utility\FormBuilder\Form;
use Planaday\Utility\FormBuilder\InputFields\LayeredCheckboxesInput;
use Planaday\Utility\FormBuilder\InputFields\MultiSelectInput;
use Planaday\Utility\FormBuilder\InputFields\RadioInput;
use Planaday\Utility\FormBuilder\InputFields\StringInput;
use Planaday\Utility\FormBuilder\LayoutItems\Header;
use Planaday\Utility\FormBuilder\LayoutItems\SubmitButton;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\SubmitStrategies\PostSubmit;
use Planaday\Utility\PluginData;

#[Transient]
class Search implements RefreshUniqueId, Tag, Feature {
	use TemplateOnlyTag;

	public function __construct(
		protected UrlHandler $urlHandler,
		protected PluginData $pluginData,
		protected CourseController $courseController,
		protected LocationController $locationController,
		protected LocalizationController $translator,
		protected SearchSettings $settings,
	) {
		$this->config = [
			"askTitle"     => $this->settings->isAskTitle(...),
			"askLocation"  => $this->settings->isAskLocation(...),
			"askLabels"    => $this->settings->isAskLabels(...),
			"askCode95"    => $this->settings->isAskCode95(...),
			"askSoob"      => $this->settings->isAskSoob(...),
			"askStap"      => $this->settings->isAskStap(...),
			"askELearning" => $this->settings->isAskELearning(...),
			"pageToSendTo" => $this->settings->getPageToSendTo(...),
			"formTitle"    => $this->settings->getFormTitle(...),
		];
	}

	public function prepareData( NodeData $nodeData ): void {
		$t = function ( string $text ) {
			return $this->translator->translate( $text );
		};

		$attributeSearchOptions = [
			[ 'value' => '1', 'label' => $t( 'Ja' ) ],
			[ 'value' => '0', 'label' => $t( 'Nee' ) ],
			[ 'value' => '-', 'label' => $t( '- (niet op zoeken)' ) ]
		];

		if ( $this->settings->getPageToSendTo() !== 0 ) {
			$urlToSendTo = $this->urlHandler->getPageUrl( $this->settings->getPageToSendTo() );
		}

		$form = ( new Form() )
			->setSubmitBehaviour(
				( new PostSubmit() )
					->setUrl( $urlToSendTo ?? '' )
			)
			->setName( 'search' )
			->addContents(
				new Header( $this->settings->getFormTitle(), 2 ),
				$formContents = ( new BasicGroup() )
					->setIndex( $this->pluginData->getFullPrefix() . PostEntities::SEARCH_FORM ),
				new SubmitButton( $t( 'Zoek' ) )
			);

		if ( $this->settings->isAskTitle() ) {
			$formContents->addContents(
				( new StringInput() )
					->setIndex( CourseSearchFieldEnum::NAME )
					->setName( $t( 'Titel' ) )
					->setPlaceholder( $t( 'Titel' ) )
					->setDescription( $t( 'Zoek op een deel van de titel van de cursus.' ) )
			);
		}

		if ( $this->settings->isAskLocation() && count( $locations = $this->getLocationsAsOptions() ) > 0 ) {
			$formContents->addContents(
				( new LayeredCheckboxesInput( new ArrayType( new IntType() ) ) )
					->setIndex( CourseSearchFieldEnum::LOCATIONS )
					->setName( $t( 'Locaties' ) )
					->setDescription( $t( 'Toon alleen cursussen die op deze locaties voorkomen.' ) )
					->setOptions( $locations )
			);
		}

		if ( $this->settings->isAskLabels() && count( $labels = $this->courseController->getUniqueLabelsCourse() ) > 0 ) {
			$formContents->addContents(
				( new MultiSelectInput( new ArrayType( new StringType() ) ) )
					->setIndex( CourseSearchFieldEnum::LABELS )
					->setName( $t( 'Labels' ) )
					->setDescription( $t( "Toon alleen cursussen met deze labels." ) )
					->setOptions( $labels )
			);
		}

		if ( $this->settings->isAskCode95() ) {
			$formContents->addContents(
				( new RadioInput( new StringType() ) )
					->setIndex( CourseSearchFieldEnum::HAS_CODE95 )
					->setName( $t( 'Heeft Code 95' ) )
					->setDescription( $t( 'Heeft de cursus een Code 95?' ) )
					->setOptions( $attributeSearchOptions )
			);
		}

		if ( $this->settings->isAskSoob() ) {
			$formContents->addContents(
				( new RadioInput( new StringType() ) )
					->setIndex( CourseSearchFieldEnum::HAS_SOOB )
					->setName( $t( 'Heeft SOOB' ) )
					->setDescription( $t( 'Heeft de cursus SOOB?' ) )
					->setOptions( $attributeSearchOptions )
			);
		}

		if ( $this->settings->isAskStap() ) {
			$formContents->addContents(
				( new RadioInput( new StringType() ) )
					->setIndex( CourseSearchFieldEnum::HAS_STAP )
					->setName( $t( 'Heeft Stap' ) )
					->setDescription( $t( 'Heeft de cursus Stap?' ) )
					->setOptions( $attributeSearchOptions )
			);
		}

		if ( $this->settings->isAskELearning() ) {
			$formContents->addContents(
				( new RadioInput( new StringType() ) )
					->setIndex( CourseSearchFieldEnum::HAS_E_LEARNING )
					->setName( $t( 'Heeft e-learning' ) )
					->setDescription( $t( 'Heeft de cursus e-learning?' ) )
					->setOptions( $attributeSearchOptions )
			);
		}

		$nodeData->data["formJson"] = json_encode( $form );
	}

	protected function getLocationsAsOptions(): array {
		$locations       = $this->locationController->getAllDB();
		$locationsByCity = [];

		foreach ( $locations as $location ) {
			$city = $location->getCity();
			if ( empty( $city ) ) {
				$city = '-';
			}
			if ( ! isset( $locationsByCity[ $city ] ) ) {
				$locationsByCity[ $city ] = [];
			}
			$locationsByCity[ $city ][] = $location;
		}

		$options = [];
		foreach ( $locationsByCity as $city => $locations ) {
			if ( count( $locations ) > 1 ) {
				$value = [];
				foreach ( $locations as $location ) {
					$value[] = [
						"label" => $location->getName(),
						"value" => $location->getId()
					];
				}
				usort( $value, function ( $a, $b ) {
					return $a["label"] <=> $b["label"];
				} );
			} else {
				$value = $locations[0]->getId();
			}

			if ( $city === '-' ) {
				$noCityOption = [
					"label" => $this->translator->translate( 'Geen stad bekend' ),
					"value" => $value
				];
			} else {
				$options[] = [
					"label" => $city,
					"value" => $value
				];
			}
		}
		usort( $options, function ( $a, $b ) {
			return $a["label"] <=> $b["label"];
		} );

		if ( ! empty( $noCityOption ) ) {
			$options[] = $noCityOption;
		}

		return $options;
	}

	public function getTagDir(): string {
		return __DIR__;
	}

	public static function getAllowedTemplates(FeatureToggleSettings $featureToggles): array {
		return [
			'Alleen formulier (voor gebruik met losse lijst)' => 'Form',
			'Formulier met Lijst weergave'                    => 'FormWithStyledList',
			'Formulier met Block weergave'                    => 'FormWithStyledBlockList',
			'Formulier met Tabel weergave'                    => 'FormWithTable',
			'Formulier met Kalender weergave'                 => 'FormWithCalendar',
			...($featureToggles->showShortcodeSettings() ? [
				'Formulier met Lijst weergave (legacy shortcode)'                    => 'FormWithList',
				'Formulier met Block weergave (legacy shortcode)'                    => 'FormWithBlockList',
				'Formulier met Block 2 weergave (legacy shortcode)'                  => 'FormWithBlock2List',
			] : [])
		];
	}
}