<?php

namespace Planaday\Html\NodeTags\Course\ListItem;

use DateTime;
use DOMNode;
use Planaday\Config\Course\General\GeneralSettings;
use Planaday\Config\General\Price\PriceSettings;
use Planaday\Entities\Course\DTO\Course;
use Planaday\Entities\DayPart\DTO\DayPart;
use Planaday\Entities\Location\DTO\Location;
use Planaday\Html\Nodes\NodeCouldNotBeCreatedException;
use Planaday\Html\Nodes\NodeData;
use Planaday\Html\Nodes\ParserNode;
use Planaday\Html\NodeTags\DayPart\ListItem\DayPartListItemSettings;
use Planaday\Html\NodeTags\Tag;
use Planaday\Html\NodeTags\TagCore;
use Planaday\Html\NodeTags\TagNotFullyInitializedException;
use Planaday\Html\Parsers\NodeParsers\TagMarkers\TestDataTag;
use Planaday\Utility\DataGrouping\Collection;
use Planaday\Utility\DependencyInjection\Attributes\Transient;

#[Transient]
class ListItem implements Tag, TestDataTag {
	use TagCore;

	public function __construct(
		protected PriceSettings $priceSettings,
		protected GeneralSettings $generalSettings,
		protected DayPartListItemSettings $dayPartListItemSettings,
		protected CourseListItemSettings $courseListItemSettings
	) {
		$this->config = [
			"showDayPartsCount"        => $this->courseListItemSettings->isShowDayPartCount(...),
			"showDayParts"             => $this->dayPartListItemSettings->isShowList(...),
			"includeELearningDayParts" => $this->generalSettings->isIncludeELearningDayParts(...),
			"showPrice"                => $this->courseListItemSettings->isShowPrice(...),
			"withTax"                  => $this->priceSettings->isIncludingTax(...),
			"showStartGuaranteed"      => $this->courseListItemSettings->isShowStartGuaranteeNotice(...),
			"showMoneyBack"            => $this->courseListItemSettings->isShowMoneyBackNotice(...),
			"showELearning"            => $this->courseListItemSettings->isShowELearningIcon(...),
			"showAvailableSpots"       => $this->courseListItemSettings->isShowAvailability(...),
			"showCode95"               => $this->courseListItemSettings->isShowCode95Icon(...),
			"showSoob"                 => $this->courseListItemSettings->isShowSoobIcon(...),
			"showLabels"               => $this->courseListItemSettings->isShowLabels(...),
			"showCostRemark"           => $this->courseListItemSettings->isShowFinancialInfo(...),
			"showDetailButton"         => $this->courseListItemSettings->isShowCourseButton(...),
			"dayPartText"              => $this->generalSettings->getDayPartText(...),
			"optionsCount"             => $this->generalSettings->isIncludeOptionInCount(...),
			"showDescription"          => $this->courseListItemSettings->isShowDescription(...),
			"maxLengthDescription"     => $this->courseListItemSettings->getMaxLengthDescription(...),
			"showLocation"             => $this->courseListItemSettings->isShowFirstLocation(...),
			"locationTemplate"         => $this->courseListItemSettings->getFirstLocationTemplate(...),
			"showIcons"                => $this->courseListItemSettings->isShowIcons(...),
		];
	}

	public function injectTestData(): void {
		$this->attributes["course"] = (new Course(1))
			->setDayParts(new Collection(
				(new DayPart(1, 1))
					->setLocations(new Collection(
						(new Location(1))
							->setCity("Test location 1")
					)),
				(new DayPart(2, 1))
					->setStartTime((new DateTime())->setTimestamp(strtotime("+1 day")))
			));
	}

	/**
	 * @throws TagNotFullyInitializedException
	 * @throws NodeCouldNotBeCreatedException
	 */
	public function getNewNode(): DOMNode&ParserNode {
		if ( ! isset( $this->originalNode ) ) {
			throw new TagNotFullyInitializedException( "The PreParser or the OriginalNode is not set" );
		}
		$nodeData = clone ($this->nodeData ?? new NodeData());

		$course = $this->attributes["course"] ?? $nodeData->data["course"] ?? null;

		if ( ! $course instanceof Course ) {
			$this->logWarning( "The course is not set" );
			return $this->originalNode->getUsableDocumentFragment();
		}

		if ( ! isset( $nodeData->data["course"] ) ) {
			$nodeData->data["course"] = $course;
		}

		/** @var null|Location $firstLocation */
		$firstLocation = $course->getEarliestDayPart()?->getLocations()->offsetGet(0);

		$nodeData->data["locationTemplateData"] = $firstLocation === null ? [] :
			[
				"name" => $firstLocation->getName(),
				"code" => $firstLocation->getCode(),
				"street" => $firstLocation->getStreet1(),
				"street_2" => $firstLocation->getStreet2(),
				"house_number" => $firstLocation->getHouseNumber(),
				"house_number_extension" => $firstLocation->getHouseNumberExtension(),
				"postal_code" => $firstLocation->getZipCode(),
				"city" => $firstLocation->getCity(),
				"country" => $firstLocation->getCountry(),
			];

		$nodeData->data["availableSpots"] = function () use ($course) {
			return $course->getUsersData()->getAvailableSpots( $this->generalSettings->isIncludeOptionInCount() );
		};

		$nodeData->data["description"] = function () use ($course){
			$tempDescriptionNode              = $this->originalNode->getNodeFromTemplate( $course->getDescription() );
			return strlen( $tempDescriptionNode->textContent ) > $this->courseListItemSettings->getMaxLengthDescription() ?
				(substr( $tempDescriptionNode->textContent, 0, (
						($this->courseListItemSettings->getMaxLengthDescription() - 3 ) > 0 ?
						$this->courseListItemSettings->getMaxLengthDescription() - 3 : 0
					)) . '...') :
					$tempDescriptionNode->textContent;
		};

		$node = $this->originalNode->getNodeFromTemplate( $this->getTemplate() );
		$node->setExtendedNodeData( $nodeData );

		return $node;
	}

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