<?php
/**
 * TaxFields.php
 *
 * @since      {$_SINCE}
 * @author     alfiopiccione <alfio.piccione@gmail.com>
 * @license    http://opensource.org/licenses/gpl-2.0.php GPL v2
 *
 * Copyright (C) 2025 POP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace WcElectronInvoice\WooCommerce\Fields;

use WcElectronInvoice\Admin\Settings\OptionPage;
use WcElectronInvoice\Providers\OrderQuery;
use function WcElectronInvoice\Functions\sanMarinoSupport;

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

/**
 * Class TaxFields
 *
 * @author alfiopiccione <alfio.piccione@gmail.com>
 */
class TaxFields
{
    /**
     * Product Fields
     *
     * @since 1.0.0
     *
     * @var array
     */
    private $fields;

    /**
     * Prefix option
     *
     * @since 1.0.0
     *
     * @var string
     */
    public static $optionPrefix = 'wc_el_inv-';

    /**
     * Return whether premium VIES / Reverse Charge runtime is enabled for the active plan.
     *
     * @return bool
     */
    public static function isPremiumViesReverseChargeEnabled(): bool
    {
        $level = get_option('pop_user_level');

        if (! $level) {
            $level = 'free';
        }

        return \WcElectronInvoice\Wizard::isUserLevelGte($level, 'basic');
    }

    /**
     * TaxFields constructor.
     *
     * @param array $fields
     */
    public function __construct(array $fields)
    {
        $this->fields = $fields;
    }

    /**
     * Get type
     *
     * @param $invoiceType
     *
     * @return string
     */
    public static function getType($invoiceType)
    {
        $outsideUE = OptionPage::init()->getOptions('hide_outside_ue');

        switch ($invoiceType) {
            case 'company':
            case 'freelance':
                $customerType = 'company';
                break;
            case 'private':
                $customerType = 'private';
                break;
            default:
                $customerType = null;
                break;
        }

        // If outside the EU for the Reverse Charge the user is always considered as private
        if ('hide' === $outsideUE && ! $customerType) {
            $customerType = 'private';
        }

        return $customerType;
    }

    /**
     * Add Product invoice fields
     *
     * @param $fields
     *
     * @return array
     * @since 1.0.0
     *
     */
    public function taxInvoiceFields($fields)
    {
        if (in_array(GeneralFields::getGeneralInvoiceOptionCountryState(), GeneralFields::getEuCountries())) {
            $fields = array_merge($fields, $this->fields);
        }

        return $fields;
    }

    /**
     * Get vies check option
     *
     * @return string|null Value set for the option or null
     * @since 3.0.0
     *
     */
    public static function getViesCheck()
    {
        if (! self::isPremiumViesReverseChargeEnabled()) {
            return '';
        }

        return apply_filters("wc_el_inv-invoice_vies_check",
            get_option(self::$optionPrefix . "invoice_vies_check")
        ) ?: '';
    }

    /**
     * Get Reverse Charge disable
     *
     * @return string|null Value set for the option or null
     * @since 3.0.0
     *
     * NB: used only for backwards compatibility from version 5.1.0
     */
    public static function getReverseChargeDisable()
    {
        return apply_filters("wc_el_inv-global_disable_reverse_charge",
            get_option(self::$optionPrefix . "global_disable_reverse_charge")
        ) ?: '';
    }

    /**
     * Get Reverse Charge active globally
     *
     * @return string|null Value set for the option or null
     * @since 3.0.0
     *
     */
    public static function getReverseChargeActiveGlobally()
    {
        if (! self::isPremiumViesReverseChargeEnabled()) {
            return '';
        }

        return apply_filters("wc_el_inv-global_active_reverse_charge",
            get_option(self::$optionPrefix . "global_active_reverse_charge")
        ) ?: '';
    }

    /**
     * Get Reverse Charge disable
     *
     * @return string|null Value set for the option or null
     * @since 3.0.0
     *
     */
    public static function getReverseChargeTaxClass()
    {
        if (! self::isPremiumViesReverseChargeEnabled()) {
            return '';
        }

        return apply_filters("wc_el_inv-reverse_charge_tax_class",
            get_option(self::$optionPrefix . "reverse_charge_tax_class")
        ) ?: '';
    }

    /**
     * Get Reverse Charge nature
     *
     * @param $type string The type of option to retrieved "ue_private, ue_company, extra_ue_private, extra_ue_company"
     *
     * @return string|null Value set for the option or null
     * @since 3.0.0
     *
     */
    public static function getReverseChargeNature(string $type): ?string
    {
        if (! self::isPremiumViesReverseChargeEnabled()) {
            return '';
        }

        if ($type) {
            $value = get_option(self::$optionPrefix . "{$type}_nature_code");
            if (GeneralFields::isItalianShop() && strpos($value, '_')) {
                $value = substr($value, 0, -2);
            }

            return apply_filters("wc_el_inv-{$type}_nature_code", $value) ?: '';
        }

        return null;
    }

    /**
     * Get Nature
     *
     * @param $order
     *
     * @return string|null
     */
    public static function getNature($order): ?string
    {
        $order            = self::resolveOrder($order);
        $sanMarinoSupport = sanMarinoSupport();

        $isOrder  = is_subclass_of($order, '\WcElectronInvoice\Providers\Order');
        $isRefund = is_subclass_of($order, '\WcElectronInvoice\Providers\OrderRefund');

        if ((! $isOrder && ! $isRefund) || ! method_exists($order, 'get_id')) {
            return null;
        }

        if (! self::getType($order->get_meta('_billing_invoice_type'))) {
            return null;
        }

        $nature = method_exists($order, 'get_nature_rc') ? $order->get_nature_rc() : '';

        // Country IT return
        if ($isOrder &&
            'SM' !== $sanMarinoSupport->shopCountry &&
            'IT' === $order->get_billing_country() &&
            '' === $nature
        ) {
            return null;
        }

        $parentOrder = null;
        if (property_exists($order, 'provider') && 0 !== (int) $order->get_parent_id()) {
            $parentOrder = OrderQuery::instance()->getProviderOrder($order->get_parent_id(), $order->provider);
        }

        $orderForMeta = $isRefund && is_object($parentOrder) ? $parentOrder : $order;
        $natureMeta   = is_object($orderForMeta) ? $orderForMeta->get_meta('nature_rc') : '';

        if ('' !== $natureMeta) {
            return $natureMeta;
        }

        return $nature;
    }

    /**
     * Get Reverse Charge normative reference
     *
     * @param $type string The type of option to retrieved "ue_private, ue_company, extra_ue_private, extra_ue_company"
     *
     * @return string|null Value set for the option or null
     * @since 3.0.0
     *
     */
    public static function getReverseChargeRefNormative($type)
    {
        if (! self::isPremiumViesReverseChargeEnabled()) {
            return '';
        }

        if (! ReverseChargeSettings::supportsNormativeReference()) {
            return '';
        }

        if ($type) {
            return apply_filters("wc_el_inv-{$type}_normative_reference",
                get_option(self::$optionPrefix . "{$type}_normative_reference")
            ) ?: '';
        }

        return null;
    }

    /**
     * Get Nature
     *
     * @param $order
     *
     * @return array|mixed|string|null
     */
    public static function getRefN($order)
    {
        $order            = self::resolveOrder($order);
        $sanMarinoSupport = sanMarinoSupport();

        if (! ReverseChargeSettings::supportsNormativeReference()) {
            return null;
        }

        $refNorm = method_exists($order, 'get_ref_norm_rc') ? $order->get_ref_norm_rc() : '';

        $isOrder  = is_subclass_of($order, '\WcElectronInvoice\Providers\Order');
        $isRefund = is_subclass_of($order, '\WcElectronInvoice\Providers\OrderRefund');

        if ((! $isOrder && ! $isRefund) || ! method_exists($order, 'get_id')) {
            return null;
        }

        if (! self::getType($order->get_meta('_billing_invoice_type'))) {
            return null;
        }

        // Country IT return
        if ($isOrder &&
            'SM' !== $sanMarinoSupport->shopCountry &&
            'IT' === $order->get_billing_country() &&
            '' === $refNorm
        ) {
            return null;
        }

        $parentOrder = null;
        if (property_exists($order, 'provider') && 0 !== (int) $order->get_parent_id()) {
            $parentOrder = OrderQuery::instance()->getProviderOrder($order->get_parent_id(), $order->provider);
        }

        $orderForMeta  = $isRefund && is_object($parentOrder) ? $parentOrder : $order;
        $natureRefNorm = is_object($orderForMeta) ? $orderForMeta->get_meta('ref_norm_rc') : '';

        if ('' !== $natureRefNorm) {
            return $natureRefNorm;
        }

        return $refNorm;
    }

    /**
     * Resolve order/stdClass to provider order where possible.
     *
     * @param $order
     *
     * @return mixed
     */
    private static function resolveOrder($order)
    {
        $isOrder  = is_subclass_of($order, '\WcElectronInvoice\Providers\Order');
        $isRefund = is_subclass_of($order, '\WcElectronInvoice\Providers\OrderRefund');
        if ($isOrder || $isRefund) {
            return $order;
        }

        if ($order instanceof \stdClass && isset($order->order_type, $order->provider, $order->id)) {
            $orderId = 'shop_order_refund' === $order->order_type ? $order->parent_id : $order->id;
            return OrderQuery::instance()->getProviderOrder($orderId, $order->provider);
        }

        if (isset($order->provider, $order->id)) {
            return OrderQuery::instance()->getProviderOrder($order->id, $order->provider);
        }

        return $order;
    }

    /**
     * checkNature
     *
     * @param $country
     * @param $customerType
     *
     * @return string|null
     */
    public static function checkNature($country, $customerType)
    {
        // if the nature is not set, the VAT will always be paid
        $prefix = null;
        if (in_array($country, GeneralFields::getEuCountries(), true)) {
            $prefix = 'ue_';
        } elseif (! in_array($country, GeneralFields::getEuCountries(), true)) {
            $prefix = 'extra_ue_';
        }

        // Set type
        switch ($customerType) {
            case 'company':
            case 'freelance':
                $type = 'company';
                break;
            default:
                $type = 'private';
                break;
        }

        // Return nature or null
        return TaxFields::getReverseChargeNature("{$prefix}{$type}") ?? null;
    }
}
