<?php

namespace Devikit\Sellsy;

use Devikit\Sellsy\Admin\Settings;
use Devikit\Sellsy\Api\Client;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Map WooCommerce tax rates to Sellsy tax IDs (French VAT focus).
 */
class TaxMapper {

	/**
	 * @var Settings
	 */
	private $settings;

	/**
	 * @var Client
	 */
	private $api_client;

	/**
	 * @param Settings $settings
	 * @param Client   $api_client
	 */
	public function __construct( Settings $settings, Client $api_client ) {
		$this->settings   = $settings;
		$this->api_client = $api_client;
	}

	/**
	 * @param float     $rate_percent
	 * @param \WC_Order $order
	 * @return int|\WP_Error Sellsy tax_id
	 */
	public function resolve_tax_id( $rate_percent, $order ) {
		$conditions = $this->get_tax_conditions( $order );

		/**
		 * Filter tax resolution conditions (PRO may force reverse charge).
		 *
		 * @param array     $conditions
		 * @param \WC_Order $order
		 */
		$conditions = apply_filters( 'devikit_sellsy_tax_conditions', $conditions, $order );

		if ( ! empty( $conditions['reverse_charge'] ) ) {
			$tax_id = $this->find_tax_id_by_vatex( 'VATEX-EU-AE' );
			if ( $tax_id ) {
				return $tax_id;
			}
			$tax_id = $this->find_tax_id_by_rate( 0.0 );
			if ( $tax_id ) {
				return $tax_id;
			}
		}

		$tax_id = $this->find_tax_id_by_rate( (float) $rate_percent );
		if ( $tax_id ) {
			return $tax_id;
		}

		return new \WP_Error(
			'sellsy_tax_unmapped',
			sprintf(
				/* translators: %s: tax rate percentage */
				__( 'No matching Sellsy tax found for rate %s%%. Create or enable this VAT rate in Sellsy.', 'invoicing-integration-for-sellsy-and-woocommerce' ),
				wc_format_decimal( (float) $rate_percent, 2 )
			)
		);
	}

	/**
	 * @param \WC_Order $order
	 * @return array
	 */
	public function get_tax_conditions( $order ) {
		return [
			'reverse_charge' => false,
			'oss'            => false,
			'billing_country'=> strtoupper( (string) $order->get_billing_country() ),
			'shipping_country' => strtoupper( (string) ( $order->get_shipping_country() ?: $order->get_billing_country() ) ),
		];
	}

	/**
	 * Extract percent rate from a WC order item.
	 *
	 * @param \WC_Order_Item $item
	 * @return float
	 */
	public function get_item_tax_rate( $item ) {
		$total    = (float) $item->get_total();
		$total_tax = (float) $item->get_total_tax();

		if ( $total > 0 && $total_tax > 0 ) {
			return round( ( $total_tax / $total ) * 100, 2 );
		}

		$taxes = $item->get_taxes();
		if ( ! empty( $taxes['total'] ) && is_array( $taxes['total'] ) ) {
			foreach ( $taxes['total'] as $rate_id => $amount ) {
				if ( (float) $amount <= 0 ) {
					continue;
				}
				$rate = \WC_Tax::_get_tax_rate( $rate_id );
				if ( is_array( $rate ) && isset( $rate['tax_rate'] ) ) {
					return (float) $rate['tax_rate'];
				}
			}
		}

		return 0.0;
	}

	/**
	 * @param float $rate
	 * @return int|null
	 */
	private function find_tax_id_by_rate( $rate ) {
		$taxes = $this->api_client->list_taxes();
		if ( is_wp_error( $taxes ) || ! is_array( $taxes ) ) {
			return null;
		}

		$target = round( (float) $rate, 2 );
		$best   = null;

		foreach ( $taxes as $tax ) {
			if ( empty( $tax['is_active'] ) ) {
				continue;
			}
			if ( ! empty( $tax['is_ecotax'] ) ) {
				continue;
			}
			$tax_rate = isset( $tax['rate'] ) ? round( (float) $tax['rate'], 2 ) : null;
			if ( $tax_rate === null ) {
				continue;
			}
			if ( abs( $tax_rate - $target ) < 0.011 ) {
				// Prefer plain VAT (no VATEX) for positive rates.
				if ( $target > 0 && ! empty( $tax['vatex'] ) ) {
					continue;
				}
				if ( $target <= 0 && ! empty( $tax['vatex'] ) ) {
					// Prefer plain 0% without exemption code when available.
					if ( $best === null ) {
						$best = (int) $tax['id'];
					}
					continue;
				}
				return (int) $tax['id'];
			}
		}

		return $best;
	}

	/**
	 * @param string $vatex
	 * @return int|null
	 */
	private function find_tax_id_by_vatex( $vatex ) {
		$taxes = $this->api_client->list_taxes();
		if ( is_wp_error( $taxes ) || ! is_array( $taxes ) ) {
			return null;
		}

		foreach ( $taxes as $tax ) {
			if ( empty( $tax['is_active'] ) ) {
				continue;
			}
			if ( isset( $tax['vatex'] ) && (string) $tax['vatex'] === (string) $vatex ) {
				return (int) $tax['id'];
			}
		}

		return null;
	}
}
