<?php

namespace Planaday\Html\Tags\Course\CourseListItem;

use Exception;
use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Config\Course\CourseSettings;
use Planaday\Entities\CostDataUtility;
use Planaday\Entities\Course\CourseController;
use Planaday\Entities\Course\CourseUtility;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\Course\Exception\CourseNotFoundException;
use Planaday\Entities\Location\LocationController;
use Planaday\Html\HtmlParser;
use Planaday\Html\Tags\DayParts\DayPartItem\DayPartItem;
use Planaday\Html\Tags\InvalidAttributesException;
use Planaday\Html\Tags\Tag;
use Planaday\Platform\PlatformAbstraction\DataHandler;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DateAndTimeUtility;
use Planaday\Utility\DependencyInjection\Container;
use Planaday\Utility\DependencyInjection\InjectionImpossibleException;

class CourseListItem extends Tag {
	const TAG = 'course-list-item';
	const DEFAULT_TEMPLATE = 'courseListItem';
	const ID_ATTRIBUTE = 'data-id';

	protected LocalizationController $localizationController;
	protected CourseController $courseController;
	protected LocationController $locationController;
	protected CourseUtility $courseUtility;
	protected DateAndTimeUtility $dateUtility;
	protected CourseSettings $courseSettings;
	protected DataHandler $dataHandler;
	protected CostDataUtility $costUtility;

	/**
	 * @param Container $registry
	 *
	 * @throws InjectionImpossibleException
	 */
	public function __construct(Container $registry) {
		$this->courseSettings    = $registry->getInstance(CourseSettings::class);
		$this->localizationController = $registry->getInstance(LocalizationController::class);
		$this->courseController = $registry->getInstance(CourseController::class);
		$this->locationController = $registry->getInstance(LocationController::class);
		$this->courseUtility = $registry->getInstance(CourseUtility::class);
		$this->dateUtility = $registry->getInstance(DateAndTimeUtility::class);
		$this->dataHandler = $registry->getInstance(DataHandler::class);
		$this->costUtility = $registry->getInstance(CostDataUtility::class);
		parent::__construct(__DIR__, self::DEFAULT_TEMPLATE, $registry);
	}

	public function buildTag(): string {
		$parser = $this->getNewParser();

		try {
			$courseIdString = $this->attributes[self::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 );

			$this->initializeCourseData($course, $parser);

			$template = $this->getTemplate();
		}
		catch (CourseNotFoundException|InvalidResponseException|InvalidAttributesException $e){
			$this->initializeExceptionData($e, $parser);

			$template = $this->getErrorTemplate();
		}

		return $parser->parse($template);
	}

	private function initializeCourseData(Course $course, HtmlParser $parser): void {

		$includeOptionsAvailability = $this->courseSettings->getGeneralSettings()->isIncludeOptionInCount();
		$overviewSettings = $this->courseSettings->getOverviewSettings();
		$maxLengthDescription = $overviewSettings->getMaxLengthDescription();

		$safeDescription = html_entity_decode($course->getDescription());
		$safeDescription = $this->dataHandler->sanitizeTextareaField($safeDescription);

		$safeDescription = strlen($safeDescription) > $maxLengthDescription ?
			substr($safeDescription, 0, $maxLengthDescription - 3) . '...' :
			$safeDescription;

		$parser->setUnsafeData('description',  substr($safeDescription,0, $maxLengthDescription));

		$firstDayPart = $course->getEarliestDayPart($this->courseSettings->getGeneralSettings()->isELearningCountsAsStart());
		if ($firstDayPart) $parser->setData('date', $this->dateUtility->getReadableDate($firstDayPart->getStartTime()));
		else $parser->setData('date', '-');
		$location = $firstDayPart?->getLocations()[0] ?? null;
		$parser->setData('location', $location?->getCity() ?? "-");

		$parser->setData('name', $course->getName());
		$parser->setData('dayPartAmount', $this->courseUtility->getDayPartCount($course, $this->courseSettings->getGeneralSettings()->isIncludeELearningDayParts()));
		$parser->setData('dayPartText', $this->courseSettings->getGeneralSettings()->getDayPartText());
		$parser->setUnsafeData('detailLink', $this->courseUtility->getDetailLink($course));
		$parser->setData('buttonText', $overviewSettings->getCourseButtonText());
		$parser->setData('availableSpots', $course->getUsersData()->getAvailableSpots($includeOptionsAvailability));
		$parser->setData('labels', implode(', ', $course->getLabels()));
		$parser->setUnsafeData('costRemark', $course->getCostsData()->getRemark());

		$parser->setData('price', $this->costUtility->getPriceString(
			$course->getCostsData(),
			false,
				true,
				isset($this->attributes['withvat']) ? $this->attributes['withvat'] == true : null
		));

		if (str_contains($this->attributes[self::TEMPLATE_ATTRIBUTE] ?? '', 'Block') && $overviewSettings->isShowDayPartList()){
			$dayPartListHtml = '';
			$dayParts = $course->getDayParts();

			foreach ($dayParts as $dayPart){
				if ($dayPart->isELearning() && $this->courseSettings->getGeneralSettings()->isIncludeELearningDayParts() === false) continue;
				$dayPartListHtml .= '<pad-' . DayPartItem::TAG . ' ' .
				                    DayPartItem::ID_ATTRIBUTE . '="' . $dayPart->getId() . '" ' .
				                    Tag::TEMPLATE_ATTRIBUTE . '="courseBlockDayPartItem" ' . '/>';
			}
			$parser->setUnsafeData('dayPartItems', $dayPartListHtml);
			$parser->setCondition('showDayPartList', true);
		}

		$parser->setCondition('showStartGuaranteed', $course->isStartGuaranteed() && $overviewSettings->isShowStartGuaranteeNotice());
		$parser->setCondition('showELearning', $course->isHasELearning() && $overviewSettings->isShowELearningIcon());
		$parser->setCondition('showMoneyBack', $course->isMoneyBackGuaranteed() && $overviewSettings->isShowMoneyBackNotice());
		$parser->setCondition('showCode95',$course->isHasCode95() && $overviewSettings->isShowCode95Icon());
		$parser->setCondition('showSoob', $course->isHasSoob() && $overviewSettings->isShowSoobIcon());
		$parser->setCondition('showLabels',  count($course->getLabels()) > 0 && $overviewSettings->isShowLabels());
		$parser->setCondition('showDetailButton', $course->getUsersData()->getAvailableSpots($includeOptionsAvailability) > 0 && $overviewSettings->isShowCourseButton());
		$parser->setCondition('isFull', $course->getUsersData()->getAvailableSpots($includeOptionsAvailability) <= 0);
		$parser->setCondition('showDescription', $overviewSettings->isShowDescription());
		$parser->setCondition('showDayParts', $overviewSettings->isShowDayPartCount());
		$parser->setCondition('showLocation', $overviewSettings->isShowFirstLocation());
		$parser->setCondition('showAvailableSpots', $overviewSettings->isShowAvailability());
		$parser->setCondition('showPrice', ($this->attributes['showprice'] ?? $overviewSettings->isShowPrice()) == 1);
		$parser->setCondition('showCostRemark', $overviewSettings->isShowFinancialInfo());

		$parser->injectAttribute(
			DayPartItem::SHOW_LOCATION_ATTRIBUTE,
			$overviewSettings->isShowLocationDayPart() ? '1' : null
		);
		$parser->injectAttribute(
			DayPartItem::SHOW_LABELS_ATTRIBUTE,
			$overviewSettings->isShowLabelsDayPart() ? '1' : null
		);
	}

	private function initializeExceptionData( Exception $exception, HtmlParser $parser): void {
		if ($exception instanceof CourseNotFoundException){
			$parser->setData('name', $this->localizationController->translate('Kon deze cursus niet vinden'));
		} elseif ($exception instanceof InvalidResponseException){
			$parser->setData('name', $this->localizationController->translate('Iets is mis gegaan'));
		} elseif ($exception instanceof InvalidAttributesException){
			$parser->setData('name', $this->localizationController->translate('Dit onderdeel is helaas niet goed ingesteld, neem contact op met de website eigenaar.'));
		}

		$parser->setUnsafeData('description', substr(html_entity_decode($exception->getMessage()),0, $this->courseSettings->getOverviewSettings()->getMaxLengthDescription()));
	}
}