<?php

namespace Planaday\Config\OptionGroups\Booking\Form;

use Planaday\Config\OptionGroups\Booking\Form\Address\AddressOptionsValidator;
use Planaday\Config\OptionGroups\Booking\Form\Company\CompanyOptionsValidator;
use Planaday\Config\OptionGroups\Booking\Form\Materials\MaterialsOptionsValidator;
use Planaday\Config\OptionGroups\Booking\Form\Student\StudentOptionsValidator;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DataFilters\InvalidFieldsException;
use Planaday\Utility\DataFilters\TypeValidator;
use Planaday\Utility\Debug\Log\Logging;

class BookingFormOptionsValidator {
	use Logging;

	/** @var AddressOptionsValidator */
	private $addressOptionsValidator;

	/** @var CompanyOptionsValidator */
	private $companyOptionsValidator;

	/** @var StudentOptionsValidator */
	private $studentOptionsValidator;

	/** @var MaterialsOptionsValidator */
	private $materialsOptionsValidator;

	/** @var TypeValidator */
	private $typeValidator;

	/** @var LocalizationController */
	private $translator;

	public function __construct(
		TypeValidator $typeValidator,
		LocalizationController $translator,
		AddressOptionsValidator $addressOptionsValidator,
		CompanyOptionsValidator $companyOptionsValidator,
		StudentOptionsValidator $studentOptionsValidator,
		MaterialsOptionsValidator $materialsOptionsValidator
	) {
		$this->addressOptionsValidator  = $addressOptionsValidator;
		$this->companyOptionsValidator  = $companyOptionsValidator;
		$this->studentOptionsValidator  = $studentOptionsValidator;
		$this->materialsOptionsValidator = $materialsOptionsValidator;
		$this->typeValidator            = $typeValidator;
		$this->translator               = $translator;
	}

	/**
	 * @param array $data
	 * @param array|null $output if valid, clean data is returned here. if not, errors will be returned here
	 *
	 * @return bool true if valid, false if not
	 */
	public function validate( array $data, ?array &$output): bool {
		$errors = [];
		$tr = $this->translator;

		try {
			$data = $this->getSafeData( $data );
		} catch ( InvalidFieldsException $e ) {
			foreach ( $e->getInvalidFields() as $field => $fieldException ) {
				$errors[ $field ] = $tr->translate(
					'Het ' . strtolower($field) . ' veld bij de boeking form opties is met ongeldige data ingevuld.'
				);
			}

			$output = $errors;
			return false;
		}

		if(empty($data[BookingFormOptionsEnum::BOOKING_FORM_TITLE] ?? true)) {
			$errors[BookingFormOptionsEnum::BOOKING_FORM_TITLE] = $tr->translate(
				'Een titel voor het boeking formulier is verplicht.'
			);
		}

		if (!$this->addressOptionsValidator->validate($data[BookingFormOptionsEnum::ADDRESS] ?? [], $addressOuput)) {
			$errors[BookingFormOptionsEnum::ADDRESS . '-isValid'] = $tr->translate('De adres opties zijn niet geldig.');
			$errors[BookingFormOptionsEnum::ADDRESS] = $addressOuput;
		} else {
			$data[BookingFormOptionsEnum::ADDRESS] = $addressOuput;
		}

		if (!$this->companyOptionsValidator->validate($data[BookingFormOptionsEnum::COMPANY] ?? [], $companyOutput)) {
			$errors[BookingFormOptionsEnum::COMPANY . '-isValid'] = $tr->translate('De bedrijf opties zijn niet geldig.');
			$errors[BookingFormOptionsEnum::COMPANY] = $companyOutput;
		} else {
			$data[BookingFormOptionsEnum::COMPANY] = $companyOutput;
		}

		if (!$this->studentOptionsValidator->validate($data[BookingFormOptionsEnum::STUDENT] ?? [], $studentOutput)) {
			$errors[BookingFormOptionsEnum::STUDENT . '-isValid'] = $tr->translate('De cursist opties zijn niet geldig.');
			$errors[BookingFormOptionsEnum::STUDENT] = $studentOutput;
		} else {
			$data[BookingFormOptionsEnum::STUDENT] = $studentOutput;
		}

		if (!$this->materialsOptionsValidator->validate($data[BookingFormOptionsEnum::MATERIALS] ?? [], $materialsOutput)) {
			$errors[BookingFormOptionsEnum::MATERIALS . '-isValid'] = $tr->translate('De materiaal opties zijn niet geldig.');
			$errors[BookingFormOptionsEnum::MATERIALS] = $materialsOutput;
		} else {
			$data[BookingFormOptionsEnum::MATERIALS] = $materialsOutput;
		}

		if ( count( $errors ) > 0 ) {
			$output = $errors;
			$this->logWarning("data is not valid", $errors);
			return false;
		}

		$output = $data;
		return true;
	}

	/**
	 * @param array $data
	 *
	 * @return array
	 * @throws InvalidFieldsException
	 */
	private function getSafeData(array $data): array {
		$tv = $this->typeValidator;

		$arrays = [
			BookingFormOptionsEnum::ADDRESS,
			BookingFormOptionsEnum::COMPANY,
			BookingFormOptionsEnum::MATERIALS,
			BookingFormOptionsEnum::STUDENT
		];

		$bool = [
			BookingFormOptionsEnum::ASK_API_ATTRIBUTES,
			BookingFormOptionsEnum::STARTED_COURSE_BOOKABLE
		];

		$string = [
			BookingFormOptionsEnum::BOOKING_FORM_TITLE
		];

		return $tv->getSafeData($data, $string, $arrays, $bool);
	}

}