<?php

namespace WPDesk\FakturyKSEF\Xml\DocumentData;

use WPDesk\CoreAlias\DocumentDecorator;
use WPDesk\FakturyKSEF\Repository\PluginSettings;
use WPDesk\FakturyKSEF\Services\DocumentKSeFSettings;
use WPDesk\FakturyKSEF\Xml\DataMapper;

class DocumentData extends DocumentDecorator {

	private PluginSettings $settings;

	protected DocumentKSeFSettings $document_ksef_settings;

	public function __construct( $document, $strategy, PluginSettings $settings, DocumentKSeFSettings $document_ksef_settings ) {
		parent::__construct( $document, $strategy );
		$this->document_ksef_settings = $document_ksef_settings;
		$this->settings               = $settings;
	}

	public function get_date_of_issue(): string {
		$date = $this->document->get_date_of_issue();
		return is_numeric( $date ) ? date( 'Y-m-d', (int) $date ) : $date;
	}

	public function get_date_of_sale(): string {
		$date = $this->document->get_date_of_sale();
		return is_numeric( $date ) ? date( 'Y-m-d', (int) $date ) : $date;
	}

	public function get_date_of_pay(): string {
		$date = $this->document->get_date_of_pay();
		return is_numeric( $date ) ? date( 'Y-m-d', (int) $date ) : $date;
	}

	/**
	 * Returns array of tax totals [ [] => total_net_sum, total_vat_sum, total_gross_sum ].
	 *
	 * @return array
	 */
	public function get_totals_by_taxes(): array {
		$tax_types = [];
		$zw_rate   = $this->settings->get_exempt_rate();
		$np_rate   = $this->settings->get_np_rate();

		foreach ( $this->get_items() as $item ) {
			if ( (string) $item['vat_type_index'] === $zw_rate ) {
				$item['vat_type'] = 'zw';
			}if ( (string) $item['vat_type_index'] === $np_rate ) {
				$item['vat_type'] = $this->document_ksef_settings->get( $this->document->get_id(), PluginSettings::DEFAULT_NP_RATE_TYPE );
			} elseif ( isset( $item['vat_type_ksef'] ) ) {
				if ( $item['vat_type_ksef'] === DataMapper::KR_ZERO_RATE ) {
					$item['vat_type'] = 'zero_rate_kr';
				} elseif ( $item['vat_type_ksef'] === DataMapper::WDT_ZERO_RATE ) {
					$item['vat_type'] = 'zero_rate_wdt';
				} elseif ( $item['vat_type_ksef'] === DataMapper::EX_ZERO_RATE ) {
					$item['vat_type'] = 'zero_rate_ex';
				}
			}

			if ( ! isset( $tax_types[ $item['vat_type'] ]['total_gross'] ) ) {
				$tax_types[ $item['vat_type'] ]['total_net']   = 0;
				$tax_types[ $item['vat_type'] ]['total_vat']   = 0;
				$tax_types[ $item['vat_type'] ]['total_gross'] = 0;
			}
			$tax_types[ $item['vat_type'] ]['total_net']   += (float) $item['net_price_sum'];
			$tax_types[ $item['vat_type'] ]['total_vat']   += (float) $item['vat_sum'];
			$tax_types[ $item['vat_type'] ]['total_gross'] += (float) $item['total_price'];
		}

		return $tax_types;
	}

	public function get_items(): array {
		$items = parent::get_items();

		$primary_zero_rate = $this->find_primary_product_zero_rate( $items );

		foreach ( $items as &$item ) {
			$item['vat_type_ksef'] = $this->determine_ksef_vat_type( $item, $primary_zero_rate );
		}

		return $items;
	}

	public function find_primary_product_zero_rate( array $items ): ?string {
		foreach ( $items as $item ) {
			if ( $this->is_product( $item ) && $this->is_zero_rate( $item ) ) {
				return $this->get_resolved_zero_rate( $item );
			}
		}
		return null;
	}

	public function determine_ksef_vat_type( array $item, ?string $fallback_zero_rate ): string {
		if ( $this->is_exempt( $item ) ) {
			return 'zw';
		}
		if ( $this->is_not_subject_to_rate( $item ) ) {
			return $this->document_ksef_settings->get( $this->document->get_id(), PluginSettings::DEFAULT_NP_RATE_TYPE );
		}

		if ( $this->is_zero_rate( $item ) ) {
			if ( $this->is_product( $item ) ) {
				return $this->get_resolved_zero_rate( $item );
			}

			return $fallback_zero_rate ?? $this->get_resolved_zero_rate( $item );
		}

		return $item['vat_type'] ?? '';
	}

	/**
	 * Resolves KSeF zero rate based on user settings or fallback to DataMapper.
	 *
	 * @param array $item
	 * @return string
	 */
	private function get_resolved_zero_rate( array $item ): string {
		$user_choice = $this->document_ksef_settings->get( $this->document->get_id(), DocumentKSeFSettings::ZERO_RATE_TYPE, 'auto' );

		switch ( $user_choice ) {
			case 'wdt':
				return DataMapper::WDT_ZERO_RATE;
			case 'ex':
				return DataMapper::EX_ZERO_RATE;
			case 'kr':
				return DataMapper::KR_ZERO_RATE;
			case 'auto':
			default:
				// Fallback to original mapper logic
				return DataMapper::get_ksef_zero_rate( $this, $item );
		}
	}

	private function is_exempt( array $item ): bool {
		return isset( $item['vat_type_index'] ) && (string) $item['vat_type_index'] === $this->settings->get_exempt_rate();
	}

	private function is_not_subject_to_rate( array $item ): bool {
		return isset( $item['vat_type_index'] ) && (string) $item['vat_type_index'] === $this->settings->get_np_rate();
	}

	private function is_zero_rate( array $item ): bool {
		return isset( $item['vat_type'] ) && (float) $item['vat_type'] === 0.0 && ! $this->is_exempt( $item ) && ! $this->is_not_subject_to_rate( $item );
	}

	private function is_product( array $item ): bool {
		return isset( $item['type'] ) && $item['type'] === 'product';
	}

	/**
	 * @param array $data
	 *
	 * @return array
	 */
	public function array_to_string_as_money( array $data ): array {
		$new_data = [];
		foreach ( $data as $key => $value ) {
			if ( ! \is_array( $value ) ) {
				$new_data[ $key ] = $this->currency_helper->string_as_money( $value );
			} else {
				$new_data[ $key ] = $this->array_to_string_as_money( $value );
			}
		}

		return $new_data;
	}

	/**
	 * Add 'save' flag for automatically saving fetched data into metadata.
	 * If new invoice is created and issued it has to have saved meta
	 * fetching data doesn't save meta if default value is used.
	 */
	public function get_exempt_reason( bool $save = true ): string {
		$reason = $this->document_ksef_settings->get( $this->document->get_id(), PluginSettings::EXEMPTION );
		if ( $save ) {
			$this->document_ksef_settings->set( $this->document->get_id(), PluginSettings::EXEMPTION, $reason );
		}
		return $this->document_ksef_settings->get( $this->document->get_id(), PluginSettings::EXEMPTION );
	}
}
