<?php

namespace DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\Value;

use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductFieldValue;
use WC_Product;
use WC_Shipping_Zones;
use WC_Countries;
use WC_Shipping_Flat_Rate;
use WC_Tax;
use WC_Shipping_Method;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductFieldArrayValue;
class GmcShippingProductFieldValue implements ProductFieldValue, ProductFieldArrayValue
{
    public const FILTER_ZONE = 'wpdesk_dropshipping_export_gmc_shipping_exclude_zone';
    public const FIELD_COUNTRY = 'country';
    public const FIELD_POSTCODE = 'postal_code';
    public const FIELD_PRICE = 'price';
    public const FIELD_SERVICE = 'service';
    public const KEY = 'gmc_shipping';
    private ?array $value = null;
    private WC_Product $product;
    public function __construct(WC_Product $product)
    {
        $this->product = $product;
    }
    public function has_array_value(): bool
    {
        return \is_array($this->get_array_value());
    }
    public function get_array_value(): ?array
    {
        if ($this->value !== null) {
            return $this->value;
        }
        $result = [];
        $zones = WC_Shipping_Zones::get_zones();
        foreach ($zones as $zone) {
            if (!isset($zone['zone_id']) && apply_filters(self::FILTER_ZONE, \false, $zone)) {
                continue;
            }
            $zone = WC_Shipping_Zones::get_zone($zone['zone_id']);
            $zone_locations = $zone->get_zone_locations();
            $zone_shipping_methods = $zone->get_shipping_methods(\true) ?? [];
            $shipping_classes = WC()->shipping->get_shipping_classes() ?? [];
            if ($zone->get_id() == 0) {
                $result = $this->get_world_shipping_costs($zone_shipping_methods, $shipping_classes);
            }
            $this->value = [...$result, ...$this->get_country_postcode_shipping_costs($zone_locations, $zone_shipping_methods, $shipping_classes)];
        }
        return $this->value;
    }
    private function get_world_shipping_costs(array $zone_shipping_methods, array $shipping_classes): array
    {
        $result = [];
        $countries = new WC_Countries();
        foreach ($zone_shipping_methods as $shipping_method) {
            $row = [];
            $row[self::FIELD_COUNTRY] = $countries->get_base_country();
            $row[self::FIELD_SERVICE] = $shipping_method->title;
            $row[self::FIELD_PRICE] = $this->get_shippping_costs($shipping_method, $shipping_classes) . ' ' . html_entity_decode(get_woocommerce_currency());
            $result[] = $row;
        }
        return $result;
    }
    private function get_country_postcode_shipping_costs(array $zone_locations, array $zone_shipping_methods, array $shipping_classes): array
    {
        $result = [];
        foreach ($zone_locations as $location) {
            foreach ($zone_shipping_methods as $shipping_method) {
                if ($location->type === 'country' || $location->type === 'postcode') {
                    $row = [];
                    $row[$location->type === 'country' ? self::FIELD_COUNTRY : self::FIELD_POSTCODE] = $location->code;
                    $row[self::FIELD_SERVICE] = $shipping_method->title;
                    $row[self::FIELD_PRICE] = $this->get_shippping_costs($shipping_method, $shipping_classes) . ' ' . html_entity_decode(get_woocommerce_currency());
                    $result[] = $row;
                }
            }
        }
        return $result;
    }
    private function get_shippping_costs(WC_Shipping_Method $shipping_method, array $shipping_classes): float
    {
        if (!empty($shipping_classes)) {
            foreach ($shipping_classes as $shipping_class) {
                if ($shipping_class->name == $this->product->get_shipping_class()) {
                    $shipping_cost = $shipping_method->instance_settings['class_cost_' . $shipping_class->term_id];
                    if ($shipping_method instanceof WC_Shipping_Flat_Rate) {
                        $product_price = floatval($this->product->get_sale_price()) == 0 ? $this->product->get_sale_price() : $this->product->get_regular_price();
                        $fake_shipping_method = new GmcShippingCosts();
                        $shipping_cost = $fake_shipping_method->evaluate_shipping_cost($shipping_cost, ['qty' => 1, 'cost' => $product_price]);
                    }
                    if (is_numeric($shipping_cost)) {
                        return $this->calculate_shipping_price($shipping_cost);
                    }
                }
            }
        }
        $shipping_method_cost = (float) 0;
        if (\property_exists($shipping_method, 'cost') && !empty($shipping_method->cost)) {
            $shipping_method_cost = (float) $shipping_method->cost;
        }
        return $this->calculate_shipping_price($shipping_method_cost);
    }
    private function calculate_shipping_price(float $shipping_cost): float
    {
        if (wc_tax_enabled()) {
            $shipping_tax_class = get_option('woocommerce_shipping_tax_class', '');
            if ($shipping_tax_class === 'inherit') {
                $shipping_tax_class = $this->product->get_tax_class();
            }
            $tax_rates = WC_Tax::get_rates($shipping_tax_class);
            $taxes = WC_Tax::calc_tax($shipping_cost, $tax_rates, \false);
            $tax_amount = WC_Tax::get_tax_total($taxes);
            $shipping_cost = round($shipping_cost + $tax_amount, wc_get_price_decimals());
        }
        return $shipping_cost;
    }
    public static function get_key(): string
    {
        return self::KEY;
    }
    public static function get_name(): string
    {
        return esc_attr__('Shipping', 'dropshipping-export-free');
    }
}
