<?php

namespace Planaday\Config\Booking\Form;

use Planaday\Config\BasicEnumMappedSetting;
use Planaday\Config\BasicSettingsLog;
use Planaday\Config\Booking\Form\Address\AddressOptionsEnum;
use Planaday\Config\Booking\Form\Address\AddressSettings;
use Planaday\Config\Booking\Form\Company\CompanyOptionsEnum;
use Planaday\Config\Booking\Form\Company\CompanySettings;
use Planaday\Config\Booking\Form\Materials\MaterialSettings;
use Planaday\Config\Booking\Form\Materials\MaterialsOptionsEnum;
use Planaday\Config\Booking\Form\Student\StudentOptionsEnum;
use Planaday\Config\Booking\Form\Student\StudentSettings;
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\DataGrouping\Collection;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\InputFields\BoolInput;
use Planaday\Utility\FormBuilder\InputFields\StringInput;
use Planaday\Utility\FormBuilder\LayoutItems\Text;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Structures\CollapsibleGroup;
use Planaday\Utility\FormBuilder\Validators\Required;

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

	protected string $bookingFormTitle = 'Cursus boeken en meteen zelf boeken';
	protected bool $askApiAttributes = false;
	protected bool $allowVouchers = false;
	protected bool $startedCourseBookable = false;

	public function __construct(
		protected LocalizationController $translator,
		protected SettingsLoader $settingsDatabase,
		protected AddressSettings $addressSettings,
		protected CompanySettings $companySettings,
		protected MaterialSettings $materialSettings,
		protected StudentSettings $studentSettings
	) {
		$this->settingsDatabase->reloadData($this, BookingFormOptionsEnum::class );
	}

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

		return ( new BasicGroup() )
			->setIndex( BookingFormOptionsEnum::class )
			->addContents(
				new Text($t("De instellingen voor het boekingsformulier.")),
				( new StringInput() )
					->setIndex( BookingFormOptionsEnum::BOOKING_FORM_TITLE->value )
					->setName( $t( "Titel boeking formulier" ) )
					->setDescription($t("De titel van het boeking formulier."))
					->setDefaultValue( $this->bookingFormTitle )
					->setPlaceholder( $t( "Cursus boeken en meteen zelf boeken" ) )
					->addSetCallback( function ( $value ) {
						$this->bookingFormTitle = $value ?? $this->bookingFormTitle;
					})
					->addValidator(
						new Required( $t( "Titel is verplicht" ) )
					),
				(new BoolInput())
					->setIndex( BookingFormOptionsEnum::STARTED_COURSE_BOOKABLE->value )
					->setName( $t( "Gestarte cursus boekbaar" ) )
					->setDescription($t("Kan nog inschrijven op een cursus die al gestart is?"))
					->setDefaultValue( $this->startedCourseBookable )
					->addSetCallback( function ( $value ) {
						$this->startedCourseBookable = $value ?? $this->startedCourseBookable;
					}),
				(new BoolInput())
					->setIndex( BookingFormOptionsEnum::SHOW_VOUCHER_INPUT->value )
					->setName( $t( "Kortingscodes toestaan" ) )
					->setDescription($t("Kunnen kortingscodes ingevuld worden in het boeking formulier?"))
					->setDefaultValue( $this->allowVouchers )
					->addSetCallback( function ( $value ) {
						$this->allowVouchers = $value ?? $this->allowVouchers;
					}),
				(new CollapsibleGroup())
					->setHeader($t("Adres"))
					->setDescription($t("De instellingen voor de adres invoervelden."))
					->addContents(
						$this->addressSettings->getFormGroup()
					),
				(new CollapsibleGroup())
					->setHeader($t("Cursist"))
					->setDescription($t("De instellingen voor de registratie van cursisten in het boeking formulier."))
					->addContents(
						$this->studentSettings->getFormGroup()
					),
				(new CollapsibleGroup())
					->setHeader($t("Bedrijf"))
					->setDescription($t("De instellingen voor de registratie van bedrijven in het boeking formulier."))
					->addContents(
						$this->companySettings->getFormGroup()
					),
				(new CollapsibleGroup())
					->setHeader($t("Materiaal"))
					->setDescription($t("Opties over de materialen die weergeven kunnen worden bij het boeken van een cursus."))
					->addContents(
						$this->materialSettings->getFormGroup()
					),
				(new BoolInput())
					->setIndex( BookingFormOptionsEnum::ASK_API_ATTRIBUTES->value )
					->setName( $t( "API attributen vragen?" ) )
					->setDescription($t("Moeten de api attributen gevraagd worden?"))
					->setDefaultValue( $this->askApiAttributes )
					->addSetCallback( function ( $value ) {
						$this->askApiAttributes = $value ?? $this->askApiAttributes;
					}),
			);
	}

	/**
	 * @return array{values:mixed[], subGroups:array[], subGroupAliases:string[]}
	 */
	public function getEnumMapping(): array {
		return [
			"values"          => [
				BookingFormOptionsEnum::BOOKING_FORM_TITLE->value => &$this->bookingFormTitle,
				BookingFormOptionsEnum::STARTED_COURSE_BOOKABLE->value => &$this->startedCourseBookable,
				BookingFormOptionsEnum::ASK_API_ATTRIBUTES->value => &$this->askApiAttributes,
				BookingFormOptionsEnum::SHOW_VOUCHER_INPUT->value => &$this->allowVouchers,
			],
			"subGroups"       => [
				BookingFormOptionsEnum::ADDRESS->value => $this->addressSettings->getEnumMapping(),
				BookingFormOptionsEnum::COMPANY->value => $this->companySettings->getEnumMapping(),
				BookingFormOptionsEnum::MATERIALS->value => $this->materialSettings->getEnumMapping(),
				BookingFormOptionsEnum::STUDENT->value => $this->studentSettings->getEnumMapping(),
			],
			"subGroupAliases" => [
				AddressOptionsEnum::class => BookingFormOptionsEnum::ADDRESS->value,
				CompanyOptionsEnum::class => BookingFormOptionsEnum::COMPANY->value,
				MaterialsOptionsEnum::class => BookingFormOptionsEnum::MATERIALS->value,
				StudentOptionsEnum::class => BookingFormOptionsEnum::STUDENT->value,
			]
		];
	}

	public function getBookingFormTitle(): string {
		$this->logUse( BookingFormOptionsEnum::BOOKING_FORM_TITLE );
		return $this->bookingFormTitle;
	}

	public function isAskApiAttributes(): bool {
		$this->logUse( BookingFormOptionsEnum::ASK_API_ATTRIBUTES );
		return $this->askApiAttributes;
	}

	public function isStartedCourseBookable(): bool {
		$this->logUse( BookingFormOptionsEnum::STARTED_COURSE_BOOKABLE );
		return $this->startedCourseBookable;
	}

	public function getAddressSettings(): AddressSettings {
		return $this->addressSettings;
	}

	public function getCompanySettings(): CompanySettings {
		return $this->companySettings;
	}

	public function getMaterialSettings(): MaterialSettings {
		return $this->materialSettings;
	}

	public function getStudentSettings(): StudentSettings {
		return $this->studentSettings;
	}

	public function isAllowVouchers(): bool {
		$this->logUse( BookingFormOptionsEnum::SHOW_VOUCHER_INPUT );
		return $this->allowVouchers;
	}

	public function getUsageLog(): Collection {
		return new Collection(
			...( $this->usageLog ?? [] ),
			...$this->addressSettings->getUsageLog(),
			...$this->companySettings->getUsageLog(),
			...$this->materialSettings->getUsageLog(),
			...$this->studentSettings->getUsageLog()
		);
	}
}