<?php

namespace Planaday\Config\Payment;

use Planaday\Config\BasicEnumMappedSetting;
use Planaday\Config\BasicSettingsLog;
use Planaday\Config\EnumMappedSettings;
use Planaday\Config\FormGroupable;
use Planaday\Config\GlobalSetting;
use Planaday\Config\SettingsLoader;
use Planaday\Config\SettingsWithForm;
use Planaday\Config\SettingsWithUsageLog;
use Planaday\Platform\PlatformAbstraction\LocalizationController;
use Planaday\Utility\DependencyInjection\Attributes\Scoped;
use Planaday\Utility\FormBuilder\Conditions\InputValueCondition;
use Planaday\Utility\FormBuilder\InputFields\BoolInput;
use Planaday\Utility\FormBuilder\InputFields\StringInput;
use Planaday\Utility\FormBuilder\LayoutItems\Text;
use Planaday\Utility\FormBuilder\Structures\BasicGroup;
use Planaday\Utility\FormBuilder\Validators\Required;

#[Scoped]
class PaymentSettings implements EnumMappedSettings, GlobalSetting, SettingsWithForm, SettingsWithUsageLog {
	use FormGroupable;
	use BasicEnumMappedSetting;
	use BasicSettingsLog;

	public static function getIndex(): string {
		return '-payment-options';
	}

	public function getTitle(): string {
		return $this->translator->translate('Betaling Instellingen');
	}

	protected bool $testPaymentActive = true;
	protected bool $paymentActive = false;
	protected bool $cancelBookingIfNoPayment = false;
	protected string $paymentNotice = "Na bevestiging kunt u meteen betalen";
	protected ?string $mollieLiveKey = null;
	protected ?string $mollieTestKey = null;
	protected bool $allowBulkPayment = true;
	protected bool $allowCompanyInvoice = false;

	public function __construct(
		protected LocalizationController $translator,
		protected SettingsLoader $settingsDatabase
	) {
		$this->settingsDatabase->reloadData($this, PaymentOptionsEnum::class );
	}

	public function save(): void {
		$this->settingsDatabase->saveData($this);
	}

	protected function createFormGroup(): BasicGroup {
		$t = function (string $string) {return $this->translator->translate($string);};

		return ( new BasicGroup() )
			->setIndex( PaymentOptionsEnum::class )
			->addContents(
				$paymentActive = (new BoolInput())
					->setIndex(PaymentOptionsEnum::PAYMENT_ACTIVE->value)
					->setName($t("Betalingen actief?"))
					->setDescription($t("Moet betalingen (via iDeal) actief zijn?"))
					->setDefaultValue($this->paymentActive)
					->addSetCallback(function ( $value ) {
						$this->paymentActive = $value ?? $this->paymentActive;
					}),
				(new BasicGroup())
					->addConditions(
						(new InputValueCondition($paymentActive))->equals()->value(true)
					)->addContents(
						(new BasicGroup())
						->addContents(
							$testPaymentActive = (new BoolInput())
								->setIndex(PaymentOptionsEnum::TEST_PAYMENT_ACTIVE->value)
								->setName($t("Test modus actief?"))
								->setDescription($t("Betalingen naar test key sturen om deze als testbetalingen doen?"))
								->setDefaultValue($this->testPaymentActive)
								->addSetCallback(function ( $value ) {
									$this->testPaymentActive = $value ?? $this->testPaymentActive;
								}),
							(new Text($t("Let op: Deze moet enkel uit worden gezet als er tenminste één testbetaling is gedaan!")))
								->addClasses("pad-warning"),
						),
						(new StringInput())
							->setIndex(PaymentOptionsEnum::MOLLIE_API_KEY_LIVE->value)
							->setName($t("Mollie Live API key"))
							->setDescription($t('Vul hier de "live API key" van Mollie in om betalingen te kunnen doen'))
							->setPlaceholder($t("Live API key"))
							->setDefaultValue($this->mollieLiveKey)
							->addSetCallback(function ( $value ) {
								$this->mollieLiveKey = $value;
							})
							->addValidator(
								(new Required($t('De API key voor live betalingen is verplicht als live betalingen actief zijn.')))
									->addCondition(
										(new InputValueCondition($testPaymentActive))->strict()->equals()->value(false)
									)
							),
						(new StringInput())
							->setIndex(PaymentOptionsEnum::MOLLIE_API_KEY_TEST->value)
							->setName($t("Mollie Test API key"))
							->setDescription($t('Vul hier de "test API key" van Mollie in om test betalingen te kunnen doen'))
							->setPlaceholder($t("Test API key"))
							->setDefaultValue($this->mollieTestKey)
							->addSetCallback(function ( $value ) {
								$this->mollieTestKey = $value;
							})
							->addValidator(
								(new Required($t('De API key voor test betalingen is verplicht als test betalingen actief zijn.')))
									->addCondition(
										(new InputValueCondition($testPaymentActive))->strict()->equals()->value(true)
									)
							),
						(new BoolInput())
							->setIndex(PaymentOptionsEnum::ALLOW_BULK_PAYMENT->value)
							->setName($t("Bulk betalingen toestaan?"))
							->setDescription($t("Kan een bedrijf meerdere deelnemers toevoegen en betalen met een enkele boeking?"))
							->setDefaultValue($this->allowBulkPayment)
							->addSetCallback(function ( $value ) {
								$this->allowBulkPayment = $value ?? $this->allowBulkPayment;
							}),
						(new BoolInput())
							->setIndex(PaymentOptionsEnum::ALLOW_COMPANY_INVOICE->value)
							->setName($t("Factuur optie voor bedrijven?"))
							->setDescription($t("Krijgen bedrijven de optie om te betalen met een factuur?"))
							->setDefaultValue($this->allowCompanyInvoice)
							->addSetCallback(function ( $value ) {
								$this->allowCompanyInvoice = $value ?? $this->allowCompanyInvoice;
							}),
						$cancelBooking = (new BoolInput())
							->setIndex(PaymentOptionsEnum::CANCEL_BOOKING_IF_NO_PAYMENT->value)
							->setName($t("Boeking annuleren?"))
							->setDescription($t("Een boeking annuleren als de betaling van deze is mislukt?"))
							->setDefaultValue($this->cancelBookingIfNoPayment)
							->addSetCallback(function ( $value ) {
								$this->cancelBookingIfNoPayment = $value ?? $this->cancelBookingIfNoPayment;
							}),
						(new BasicGroup())
							->addConditions(
								(new InputValueCondition($cancelBooking))->strict()->equals()->value(true)
							)->addContents(
								(new Text($t("Let op: van een eventuele geannuleerde boeking wordt geen communicatie verstuurd!")))
									->addClasses("pad-warning"),
							),
						(new StringInput())
							->setIndex(PaymentOptionsEnum::PAYMENT_NOTICE->value)
							->setName($t('Toelichting op boekingsformulier'))
							->setDescription($t("Tekst bij boekingformulier, zodat de klant weet dat zij kunnen betalen"))
							->setPlaceholder($t("Na bevestiging kunt u meteen betalen"))
							->setDefaultValue($this->paymentNotice)
							->addSetCallback(function ( $value ) {
								$this->paymentNotice = $value ?? $this->paymentNotice;
							})
					),
			);
	}

	/**
	 * @return array{values:mixed[], subGroups:array[], subGroupAliases:string[]}
	 */
	public function getEnumMapping(): array {
		return [
			"values"    => [
				PaymentOptionsEnum::TEST_PAYMENT_ACTIVE->value          => &$this->testPaymentActive,
				PaymentOptionsEnum::PAYMENT_ACTIVE->value               => &$this->paymentActive,
				PaymentOptionsEnum::CANCEL_BOOKING_IF_NO_PAYMENT->value => &$this->cancelBookingIfNoPayment,
				PaymentOptionsEnum::PAYMENT_NOTICE->value               => &$this->paymentNotice,
				PaymentOptionsEnum::MOLLIE_API_KEY_TEST->value          => &$this->mollieTestKey,
				PaymentOptionsEnum::MOLLIE_API_KEY_LIVE->value          => &$this->mollieLiveKey,
				PaymentOptionsEnum::ALLOW_BULK_PAYMENT->value           => &$this->allowBulkPayment,
				PaymentOptionsEnum::ALLOW_COMPANY_INVOICE->value        => &$this->allowCompanyInvoice,
			],
			"subGroups" => [],
			"subGroupAliases" => []
		];
	}

	public function isTestPaymentActive(): bool {
		$this->logUse(PaymentOptionsEnum::TEST_PAYMENT_ACTIVE);
		return $this->testPaymentActive;
	}

	public function isPaymentActive(): bool {
		$this->logUse(PaymentOptionsEnum::PAYMENT_ACTIVE);
		return $this->paymentActive;
	}

	public function isCancelBookingIfNoPayment(): bool {
		$this->logUse(PaymentOptionsEnum::CANCEL_BOOKING_IF_NO_PAYMENT);
		return $this->cancelBookingIfNoPayment;
	}

	public function getPaymentNotice(): string {
		$this->logUse(PaymentOptionsEnum::PAYMENT_NOTICE);
		return $this->paymentNotice;
	}

	public function getMollieLiveKey(): ?string {
		$this->logUse(PaymentOptionsEnum::MOLLIE_API_KEY_LIVE);
		return $this->mollieLiveKey;
	}

	public function getMollieTestKey(): ?string {
		$this->logUse(PaymentOptionsEnum::MOLLIE_API_KEY_TEST);
		return $this->mollieTestKey;
	}

	public function isAllowBulkPayment(): bool {
		$this->logUse(PaymentOptionsEnum::ALLOW_BULK_PAYMENT);
		return $this->allowBulkPayment;
	}

	public function isAllowCompanyInvoice(): bool {
		$this->logUse(PaymentOptionsEnum::ALLOW_COMPANY_INVOICE);
		return $this->allowCompanyInvoice;
	}

	public function isPaymentPossible(): bool {
		return $this->paymentActive && (
			$this->testPaymentActive ?
				$this->mollieTestKey !== null :
				$this->mollieLiveKey !== null
			);
	}

	public function isPaymentLive(): bool {
		return $this->isPaymentPossible() && $this->testPaymentActive === false;
	}

	public function getActiveMollieKey(): ?string {
		return $this->testPaymentActive ? $this->mollieTestKey : $this->mollieLiveKey;
	}
}