<?php

namespace Planaday\Html\Tags\Form\Booking\DayPartsChecklist;

use ArrayAccess;
use Countable;
use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Config\Course\General\GeneralSettings;
use Planaday\Entities\Booking\PostRequest\BookingFormFieldEnum;
use Planaday\Entities\CostDataUtility;
use Planaday\Entities\Course\CourseController;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\DTO\DayPartDisplayTypes;
use Planaday\Entities\Course\Exception\CourseNotFoundException;
use Planaday\Entities\DayPart\DTO\DayPart;
use Planaday\Html\Tags\Form\DataInputFieldTag;
use Planaday\Html\Tags\InvalidAttributesException;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DateAndTimeUtility;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;
use Traversable;

class DayPartsChecklist extends DataInputFieldTag {
	const TAG = 'daypart-checklist';
	const DEFAULT_TEMPLATE = 'dayPartsChecklist';
	const COURSE_ID_ATTRIBUTE = 'data-course-id';
	const SHOW_PRICES_ATTRIBUTE = 'data-show-prices';
	protected string $fieldName = BookingFormFieldEnum::DAY_PARTS;

	protected CourseController $courseController;
	protected CostDataUtility $costUtility;
	protected GeneralSettings $generalSettings;
	protected LocalizationController $translator;
	protected DateAndTimeUtility $dateTimeUtility;
	protected bool $showPrices = false;

	/**
	 * @param Container $registry
	 *
	 * @throws InjectionImpossibleException
	 */
	public function __construct(Container $registry) {
		$this->generalSettings  = $registry->getInstance(GeneralSettings::class);
		$this->courseController = $registry->getInstance(CourseController::class);
		$this->dateTimeUtility = $registry->getInstance(DateAndTimeUtility::class);
		$this->costUtility = $registry->getInstance(CostDataUtility::class);
		$this->translator = $registry->getInstance(LocalizationController::class);
		parent::__construct(__DIR__, self::DEFAULT_TEMPLATE, $registry);
	}

	public function buildTag(): string {
		$parser = $this->getNewParser();
		$parser->setData('dayPartName', $this->generalSettings->getDayPartText());

		try{
			$this->showPrices = key_exists(self::SHOW_PRICES_ATTRIBUTE, $this->attributes);
			$courseIdString = $this->attributes[self::COURSE_ID_ATTRIBUTE] ?? null;
			if ($courseIdString === null) throw new InvalidAttributesException();

			$courseId = filter_var($courseIdString, FILTER_VALIDATE_INT);
			if ($courseId === false) throw new InvalidAttributesException();

			$course = $this->courseController->getCourse($courseId, true);
			$dayParts = $course->getDayParts();

			$checklist = $this->getDayPartChecklist($dayParts, $course);
		}
		catch ( InvalidResponseException ) {
			$checklist = $this->getNewParser()->parse($this->getErrorTemplate('', 'serverError'));
		}
		catch ( CourseNotFoundException ) {
			$checklist = $this->getNewParser()->parse($this->getErrorTemplate('', 'courseNotFound'));
		}
		catch ( InvalidAttributesException ) {
			$checklist = $this->getNewParser()->parse($this->getErrorTemplate('', 'attributeError'));
		}

		$parser->setUnsafeData('checklist', $checklist);
		return $parser->parse($this->getTemplate());
	}

	/**
	 * @param ArrayAccess<int|string, DayPart>&Traversable<int|string, DayPart>&Countable $dayParts
	 * @param Course $course
	 *
	 * @return string
	 */
	private function getDayPartChecklist(ArrayAccess&Traversable&Countable $dayParts, Course $course):string {
		$output = '';

		foreach ($dayParts as $dayPart){
			$parser = $this->getNewParser();

			if ($course->getDayPartDisplayType() === DayPartDisplayTypes::AllSelectedImmutable) $parser->setData('dataDisabled', "data-disabled");

			if (
				$course->getDayPartDisplayType() === DayPartDisplayTypes::AllSelectedImmutable ||
				$course->getDayPartDisplayType() === DayPartDisplayTypes::AllSelected
			) $parser->setData('dataChecked', "data-checked");

			$parser->setData('dayPartName', $dayPart->getName());
			$parser->setData('dayPartId', $dayPart->getId());

			$startDate = $this->dateTimeUtility->getReadableDate($dayPart->getStartTime());

			if ($dayPart->isELearning()){
				if ($dayPart->getStartTime()->format('Y') !== '1970')
					$parser->setData('dayPartDate', $this->translator->translate('vanaf') . ' ' . $startDate);
			} else {
				$startTime = $dayPart->getStartTime()->format('H:i');

				$parser->setData('dayPartDate', $this->translator->translate('op') . ' ' . $startDate . ' ' . $this->translator->translate('om') . ' ' . $startTime);
			}

			$priceLabel = $this->costUtility->getPriceString($dayPart->getCostsData(), false, true);

			if ( $this->showPrices ) $parser->setData('priceLabel', "($priceLabel)");

			$output .= $parser->parse(
				$this->getTemplate(
					'DayPart',
					$course->getDayPartDisplayType() === DayPartDisplayTypes::MaxOneSelected ? 'dayPartRadio' : null
				)
			);
		}

		return $output;
	}
}