<?php

namespace Planaday\Entities\Booking\Form\DayParts;

use Exception;
use Planaday\Entities\Booking\DTO\BookingForm;
use Planaday\Entities\Booking\Form\BookingFieldsEnum;
use Planaday\Entities\CostDataUtility;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\DTO\DayPartDisplayTypes;
use Planaday\Entities\DayPart\DTO\DayPart;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DataGrouping\Collection;
use Planaday\Utility\DateAndTimeUtility;
use Planaday\Utility\Debug\Log\Logging;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\DataTypes\ArrayType;
use Planaday\Utility\FormBuilder\DataTypes\IntType;
use Planaday\Utility\FormBuilder\InputFields\MultiSelectInput;
use Planaday\Utility\FormBuilder\InputFields\RadioInput;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Validators\Required;

#[Scoped]
class DayPartsFormFactory {
	use Logging;

	public function __construct(
		protected LocalizationController $localizationController,
		protected DateAndTimeUtility $dateAndTimeUtility,
		protected CostDataUtility $costDataUtility,
		protected DayPartsSettings $settings,
	) {}

	public function getFormForObject(BookingForm $bookingForm, Course $course): BasicGroup{
		$t = function (string $text) {
			return $this->localizationController->translate($text);
		};

		$outputGroup = (new BasicGroup());

		$displayType = $course->getDayPartDisplayType();

		$options = [];
		foreach ($course->getDayParts() as $dayPart) {
			$options[] = [
				'value' => $dayPart->getId(),
				'label' => $this->getDayPartLabel($dayPart, $course),
			];
		}

		if ($displayType === DayPartDisplayTypes::MaxOneSelected){
			$input = ( new RadioInput(new IntType()) )
				->addSetCallback( function ( $value ) use ( $bookingForm ) {
					$bookingForm->setDayParts( new Collection($value) );
				})
				->setDefaultValue( null );
		} else {
			$input = ( new MultiSelectInput(new ArrayType(new IntType())) )
				->addSetCallback( function ( $value ) use ( $bookingForm ) {
					$bookingForm->setDayParts( Collection::fromArray($value ?? []) );
				})
				->setDefaultValue( $displayType === DayPartDisplayTypes::AllSelected ? $course->getDayPartIds() : [] );
		}

		$input->setIndex(BookingFieldsEnum::DayPartsToBook->value)
			->setName($this->settings->getTitle() . " *")
			->setDescription($t("Waar wilt u zich op inschrijven?"))
			->setOptions($options)
			->addValidator(
				(new Required($t("Er moet minimaal 1 geselecteerd zijn")))
			);

		$outputGroup->addContents($input);

		return $outputGroup;
	}

	protected function getDayPartLabel(DayPart $dayPart, Course $course): string {
		$t = function (string $text) {
			return $this->localizationController->translate($text);
		};

		$output = $dayPart->getName();

		if ($this->settings->isShowDate() && $dayPart->getStartTime()->format('Y') !== '1970')
			$output .= ' ' . ($dayPart->isELearning() ? $t('vanaf') : $t('op')) . ' ' . $this->dateAndTimeUtility->getReadableDate($dayPart->getStartTime());
		if ($this->settings->isShowTime() && $dayPart->getStartTime()->format('Y') !== '1970' && !$dayPart->isELearning())
			$output .= ' ' . $t('om') . ' ' . $dayPart->getStartTime()->format('H:i');
		if ($this->settings->isShowLocation() && !$dayPart->isELearning() && (($dayPart->getLocations()[0] ?? null) !== null))
			$output .= ' ' . $t('in') . ' ' . $dayPart->getLocations()[0]->getCity();

		if (
			$this->settings->isShowPrice() &&
		    (!$this->settings->isOnlyShowPriceIfPerDayPart() || $course->isPriceFromDayParts())
		) $output .= ' ' . $t('voor') . ' ' . $this->costDataUtility->getPriceString(
				$dayPart->getCostsData(),
				$this->settings->isShowBothWithAndWithoutTaxPrice(),
				true
			);

		return $output;
	}
}