<?php

namespace Planaday\Entities\Booking\Form\Materials;

use Planaday\Api\ApiException\InvalidResponseException;
use Planaday\Entities\Booking\DTO\BookingForm;
use Planaday\Entities\CostDataUtility;
use Planaday\Entities\Course\CourseController;
use Planaday\Entities\Course\DTO\CourseMaterial;
use Planaday\Entities\Course\Exception\CourseNotFoundException;
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\LayoutItems\Header;
use Planaday\Utility\FormBuilder\LayoutItems\Html;
use Planaday\Utility\FormBuilder\Structure;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;

#[Scoped]
class MaterialFormFactory {
	public function __construct(
		protected CourseController $courseController,
		protected LocalizationController $localizationController,
		protected CostDataUtility $costDataUtility,
		protected MaterialSettings $settings,
	) {}

	/**
	 * @param BookingForm $bookingForm
	 *
	 * @return Structure
	 * @throws InvalidResponseException
	 * @throws CourseNotFoundException
	 */
	public function getFormForObject(BookingForm $bookingForm): Structure{
		/** @var CourseMaterial[] $materials */
		$materials = $this->courseController->getMaterialsCourse($bookingForm->getCourseId());

		$description = $this->settings->getMaterialsFormDescription();

		$outputGroup = (new BasicGroup())
			->addContents(
				new Header( $this->settings->getMaterialsFormTitle(), 4 ),
			);

		if ( !empty( $description ) ){
			$outputGroup->addContents(
				( new BasicGroup() )
					->addContents(
						new Html( $description )
					)->addClasses("pad-material-description")
			);
		}

		foreach ($materials as $material) {
			$outputGroup->addContents(
				( new BoolInput() )
					->setIndex( $material->getId() )
					->setName( $this->getMaterialName( $material ) )
					->setDescription( $this->settings->isShowDescriptionMaterials() ? $material->getDescription() : "" )
					->setDefaultValue( false )
					->addSetCallback( function ( $value ) use ( $material, $bookingForm ) {
						$selectedMaterials = $bookingForm->getMaterials();

						if ( $value ) {
							$selectedMaterials[] = $material->getId();
						} else {
							$selectedMaterials = array_filter( Collection::fromIterable($selectedMaterials)->toArray(), function ( $selectedMaterial ) use ( $material ) {
								return $selectedMaterial !== $material->getId();
							});
						}

						$bookingForm->setMaterials( $selectedMaterials );
					})
			);
		}

		return $outputGroup;
	}

	protected function getMaterialName( CourseMaterial $material ): string {
		$output = $material->getName();

		if ( $this->settings->isShowPrice() ) {
			$priceLabel = $this->costDataUtility->getPriceString(
				$material->getCostsData(),
				$this->settings->isShowBothWithAndWithoutTaxPrice(),
				$material->isInvoicedPerStudent()
			);

			if ( $material->isInvoicedPerCompany() && $material->getAmount() > 1){
				$priceLabel .= ' x ' . $material->getAmount() . ' ' . $this->localizationController->translate('stuks');
			}

			$output .= " ($priceLabel)";
		}

		return $output;
	}
}