<?php

namespace Soft_Tehnica\Freya_Sync_Service\Services;

use Automattic\WooCommerce\StoreApi\Exceptions\RouteException;
use Exception;
use Soft_Tehnica\Freya_Sync_Service\Data\FsPickupMethod;
use Soft_Tehnica\Freya_Sync_Service\Data\FsShippingMethod;
use Soft_Tehnica\Freya_Sync_Service\Data\Location;
use Soft_Tehnica\Freya_Sync_Service\Data\Notification;
use Soft_Tehnica\Freya_Sync_Service\Data\Woocommerce\CartItemWrapper;
use Soft_Tehnica\Freya_Sync_Service\STUtils\STView;
use WC_Order;
use WC_Product;
use WC_Shipping_Method;
use WC_Shipping_Zones;
use WP_Query;

class CartService
{

    public ?string $countyRestriction;
    public ?string $companyUid;
    public ?string $defaultLocationUid;
    public array $addressOnPages = [];
    public $addressRequestOnPages;
    public $enableMultiSubdomain;
    public $isRunningOnLandingPageInstance;
    public bool $isRestApi = false;
    public ?string $noAddressFoundMessage;
    public bool $noPolygons;
    public bool $showAllProductsOnNoLocation = false;
    public bool $needToAskAddressOnLoad      = true;
    public bool $triggerModalAddressAuto     = true;

    private bool $fsShippingEnabled = false;
    private bool $fsPickupEnabled   = false;

    public function __construct()
    {
        $this->setLocalData();
        $this->init();
        $zones = WC_Shipping_Zones::get_zones();

        foreach ( $zones as $zone ) {
            /** @var WC_Shipping_Method $method */
            foreach ( $zone['shipping_methods'] as $method ) {
                if ( $method->id === 'fs_pickup_method' && $method->enabled === 'yes' ) {
                    $this->fsPickupEnabled = true;
                }

                if ( $method->id === 'fs_shipping_method' && $method->enabled === 'yes' ) {
                    $this->fsShippingEnabled = true;
                }
            }
        }

        SessionService::get()->updateSessionWithActiveShipping(
            $this->fsShippingEnabled,
            $this->fsPickupEnabled
        );

        $availableLocations = LocationService::get()->getAvaliableLocations();
        SessionService::get()->setFetchedLocations( $availableLocations );

        $defaultLocationUid = PluginSettings::get()->getDefaultLocationUid();

        if (PluginSettings::get()->isPolygonsDisabled() && $defaultLocationUid !== null) {
            /** @var Location|null $defaultLocation */
            $defaultLocation = null;
            foreach ($availableLocations as $location) {
                if ($location->uid === $defaultLocationUid) {
                    $defaultLocation = $location;
                }
            }

            if ($defaultLocation) {
                SessionService::get()->setLocationName($defaultLocation->name);
                SessionService::get()->setLocationUid($defaultLocation->uid);
            }
        }

        AddressService::get()->setCartLocationFromSession();

        add_shortcode(
            'fss_need_address',
            [ $this, 'need_address_shortcode' ]
        );
        add_shortcode(
            'fss_need_address_minimal',
            [ $this, 'need_address_minimal_shortcode' ]
        );
        add_shortcode(
            'fss_need_address_info',
            [ $this, 'need_address_info_shortcode' ]
        );
        add_shortcode(
            'fss_need_address_link',
            [ $this, 'need_address_link_shortcode' ]
        );
    }

    public function need_address_shortcode(): string
    {
        return $this->renderNeedAddressContent();
    }

    public function need_address_minimal_shortcode(): string
    {
        return $this->renderNeedAddressMinimalContent();
    }

    public function need_address_info_shortcode(): string
    {
        return $this->renderNeedAddressInfo();
    }

    public function need_address_link_shortcode(): string
    {
        return $this->renderNeedAddressLink();
    }

    public function setLocalData(): void
    {
        $options = get_option( 'fs_option_settings', [] );

        $this->companyUid                     = ( isset( $options['fsCompanyUid'] ) ) ? $options['fsCompanyUid'] : null;
        $this->defaultLocationUid             = ( isset( $options['fsDefaultLocationUid'] ) ) ? $options['fsDefaultLocationUid'] : null;
        $this->addressOnPages                 = ( isset( $options['fsAddressRequestOnPages'] ) ) ? $options['fsAddressRequestOnPages'] : [];
        $this->enableMultiSubdomain           = ( isset( $options['fsEnableMultiSubdomain'] ) ) ? $options['fsEnableMultiSubdomain'] : null;
        $this->isRunningOnLandingPageInstance = ( isset( $options['fsIsRunningOnLandingPageInstance'] ) ) ? $options['fsIsRunningOnLandingPageInstance'] : null;
        $this->countyRestriction              = ( isset( $options['fsCountyRestriction'] ) ) ? $options['fsCountyRestriction'] : null;
        $this->noAddressFoundMessage          = ( isset( $options['fsNoAddressFoundMessage'] ) ) ? $options['fsNoAddressFoundMessage'] : null;
        $this->noPolygons                     = isset( $options['fsNoPolygons'] ) && $options['fsNoPolygons'] === 1;
        $this->showAllProductsOnNoLocation    = PluginSettings::get()->getShowAllProductsOnNoLocation();
    }

    public function renderNeedAddressContent(): string
    {
        return STView::render( 'need-address', [
            'address'      => SessionService::get()->getUserAddress(),
            'pickup'       => SessionService::get()->isPickup(),
            'hasDelivery'  => $this->fsShippingEnabled,
            'hasPickup'    => $this->fsPickupEnabled,
            'locationName' => SessionService::get()->getLocationName(),
            'minimal'      => false,
        ] );
    }

    public function renderNeedAddressMinimalContent(): string
    {
        return STView::render( 'need-address', [
            'address'      => SessionService::get()->getUserAddress(),
            'pickup'       => SessionService::get()->isPickup(),
            'hasDelivery'  => $this->fsShippingEnabled,
            'hasPickup'    => $this->fsPickupEnabled,
            'locationName' => SessionService::get()->getLocationName(),
            'minimal'      => true,
        ] );
    }

    public function renderModal(): string
    {
        return STView::render( 'modal-address', [
            'noAddressMessage'  => $this->noAddressFoundMessage,
            'pickup'            => SessionService::get()->isPickup(),
            'userAddress'       => SessionService::get()->getUserAddress(),
            'hasPickup'         => $this->fsPickupEnabled,
            'hasDelivery'       => $this->fsShippingEnabled,
            'activeLocationUid' => SessionService::get()->getLocationUid(),
            'locations'         => SessionService::get()->getFetchedLocations(),
            'hasFA'             => is_plugin_active( 'font-awesome/index.php' ),
            'hideDismiss'       => PluginSettings::get()->hideModalDismiss(),
        ] );
    }

    public function renderNoAddress(): string
    {
        return STView::render( 'no-address' );
    }

    public function renderNeedAddressInfo(): string
    {
        return STView::render( 'need-address-info', [
            'address'      => SessionService::get()->getUserAddress(),
            'pickup'       => SessionService::get()->isPickup(),
            'locationName' => SessionService::get()->getLocationName(),
        ] );
    }

    public function renderNeedAddressLink(): string
    {
        return STView::render( 'need-address-link' );
    }

    public function check_cart_item_locations(): void
    {
        if ( ! wc()->cart ) {
            return;
        }

        $locationUid = SessionService::get()->getLocationUid()
                       ?? PluginSettings::get()->getDefaultLocationUid();

        $locationName = SessionService::get()->getLocationName() ?? ' - ';

        if ( ! isset( $locationUid ) ) {
            return;
        }

        foreach ( wc()->cart->get_cart() as $k => $item ) {
            $wrapper = new CartItemWrapper( $item );

            $product = $wrapper->getProductData();

            if ( ! $product ) {
                continue;
            }

            /** @var array<string, array{name: string, price: float}>|null $ext */
            $ext = $product->get_meta( 'location_ext' );
            /** @var string|null $locationUid */
            $productLocationUid = $product->get_meta( 'location_uid' );

            $found = false;

            if ( is_string( $productLocationUid ) && $locationUid === $productLocationUid ) {
                $found = true;
            }

            if ( is_array( $ext ) ) {
                foreach ( $ext as $uid => $data ) {
                    if ( $uid === $locationUid ) {
                        $found = true;
                        break;
                    }
                }
            }

            if ( ! $found ) {
                wc()->cart->remove_cart_item( $k );
                wc_add_notice(
                    "Produsul {$product->get_name()} nu este disponibil în locația $locationName. Acesta a fost eliminat din coșul dumneavoastră.",
                    'error'
                );
            }
        }
    }

    public function isAddressSet(): bool
    {
        if ( SessionService::get()->isPickup() ) {
            return true;
        }
        $userAddress = SessionService::get()->getUserAddress();

        return isset( $userAddress ) && strlen( $userAddress ) > 0;
    }

    public function isProductInActiveLocation( WC_Product $product ): bool
    {
        $locationUid = SessionService::get()->getLocationUid()
                       ?? PluginSettings::get()->getDefaultLocationUid();

        if ( ! isset( $locationUid ) ) {
            return false;
        }

        $meta = $product->get_meta( 'location_uid' );

        /** @var array<string, array{name: string, price: float}>|false $ext */
        $ext = $product->get_meta( 'location_ext' );

        if ( $ext ) {
            foreach ( $ext as $uid => $value ) {
                if ( $uid === $locationUid ) {
                    return true;
                }
            }
        }

        if ( $meta && $meta === $locationUid ) {
            return true;
        }

        return false;
    }

    /**
     * @hook woocommerce_add_to_cart_validation
     *
     * Folosit pentru pagina de produs și versiuni mai vechi de woocommerce (fără ajax)
     */
    public function validate_cart_item_old(
        bool $passed,
        int $product_id
    ): bool {
        // Dacă suntem în store API, lăsăm celălalt hook să-și facă treaba
        if ( fss_is_wc_store_api() ) {
            return $passed;
        }

        if ( ! $this->isAddressSet() ) {
            SessionService::get()->setFlashNeedLocation( true );
            NotificationManager::get()->push( new Notification(
                'addtocart-prevent',
                'Nu ați configurat preferințele de livrare. Puteți face acest lucru din partea de sus a paginii.'
            ) );

            return false;
        }

        $product = wc_get_product( $product_id );

        if ( ! $product ) {
            return $passed;
        }

        if ( ! $this->isProductInActiveLocation( $product ) ) {
            wc_add_notice(
                'Acest produs nu este servit de locația selectată',
                'error'
            );

            return false;
        }

        return $passed;
    }

    /**
     * @hook woocommerce_store_api_validate_add_to_cart
     *
     * woocommerce >= 7.2
     *
     * Pentru adăugarea în coș prin ajax (store api)
     *
     * @throws Exception
     */
    public function validate_cart_item_new( WC_Product $product ): void
    {
        $this->validate_product_with_throw( $product );
    }

    public function validate_cart_item_qty_update(
        string $cart_item_key,
        int $quantity,
        int $old_quantity,
        \WC_Cart $cart
    ): void {
        $cart_item = $cart->get_cart_item( $cart_item_key );

        if ( ! isset( $cart_item['product_id'] ) ) {
            return;
        }

        $product = wc_get_product( $cart_item['product_id'] );

        if ( ! $product ) {
            return;
        }

        $this->validate_product_with_throw( $product );
    }

    private function validate_product_with_throw( WC_Product $product ): void
    {
        if ( ! $this->isAddressSet() ) {
            throw new RouteException( 'freya_sync_validate_error', 'Nu s-a putut adăuga produsul în coș deoarece nu ați ales locația de servire.', 400 );
        }

        if ( ! $this->isProductInActiveLocation( $product ) ) {
            throw new RouteException( 'freya_sync_validate_error', 'Acest produs nu este servit de locația de servire activă', 400 );
        }
    }

    public function finalHtmlResponse( $wpPageContent ): string
    {
        $addon  = $this->renderModal();
        $pageId = get_queried_object_id();

        $modalDismissed = SessionService::get()->isAddressModalDismissed();

        $userAddressDetails = SessionService::get()->getUserAddressInputs();

        $PAGE_SHOULD_SHOW_MODAL = in_array(
            $pageId,
            PluginSettings::get()->getPagesThatRequestAddress()
        );
        $COMPANY_HAS_POLYGONS   = PluginSettings::get()->isPolygonsDisabled();
        $USER_ADDRESS_SET       = isset( $userAddressDetails );

        if (
            $PAGE_SHOULD_SHOW_MODAL &&
            $this->triggerModalAddressAuto &&
            ! $modalDismissed &&
            $COMPANY_HAS_POLYGONS &&
            ! $USER_ADDRESS_SET
        ) {
            $addon .= "<script> const j = jQuery.noConflict(); j.('#fss-modal').addClass('modal-visible') </script>";
        }

        return str_replace(
            '</body>',
            sprintf( '%s</body>', $addon ),
            $wpPageContent
        );
    }

    public function setMinimOrderValue(): void
    {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
            return;
        }

        $taxData = SessionService::get()->getTax();

        if ( is_null( $taxData ) || $taxData->minimumFee === 0. ) {
            return;
        }

        if ( floatval( WC()->cart->get_displayed_subtotal() ) < $taxData->minimumFee ) {
            $value     = number_format( $taxData->minimumFee, 2 );
            $diffValue = number_format(
                abs( floatval( WC()->cart->get_displayed_subtotal() ) - $taxData->minimumFee ),
                2
            );

            $message = sprintf(
                "Comanda minimă pentru adresa dumnavoastră este în valoare de %f RON.\nMai trebuie să adăugați produse în valoare de %f RON pentru a finaliza comanda.",
                $value,
                $diffValue
            );

            wc_clear_notices();
            wc_add_notice( $message, 'error' );
        }
    }

    public function destroySession(): void
    {
        SessionService::get()->clearSessionAfterOrder();
    }

    public function initRestApi( $args ): void
    {
        if ( $args ) {
            $this->isRestApi = true;
        }
    }

    public function filterProductsByLocation( WP_Query $query ): void
    {
        if ( ! $query->is_main_query() ) {
            return;
        }

        $locationUid = SessionService::get()->getLocationUid();

        if ( is_null( $locationUid ) && $this->showAllProductsOnNoLocation ) {
            return;
        } elseif ( is_null( $locationUid ) ) {
            $locationUid = PluginSettings::get()->getDefaultLocationUid();
        }

        if ( is_null( $locationUid ) ) {
            return;
        }

        $query->set( 'meta_query', [
            'relation' => 'OR',
            [
                'key'     => 'location_uid',
                'compare' => '=',
                'value'   => "$locationUid",
            ],
            [
                'key'     => 'location_ext',
                'compare' => 'LIKE',
                'value'   => "$locationUid",
            ],
        ] );
    }

    /**
     * @ajax cart_service_service_modal_dismissed
     */
    public function setModalDismissed(): void
    {
        check_ajax_referer( 'wp_rest' );
        SessionService::get()->setAddressModalDismissed( true );
    }

    public function onOrderPlaced( $id ): void
    {
        SessionService::get()->clearSessionAfterOrder();
    }

    public function onWoocommerceBillingFields( array $fields ): array
    {
        $fields['billing']['billing_email']['required'] = false;

        return $fields;
    }

    public function edit_blocks_checkout_fields( array $locale ): array
    {
        foreach ( $locale as &$fields ) {
            if ( SessionService::get()->isPickup() ) {
                if ( PluginSettings::get()->hideAddressFieldsOnPickup() ) {
                    $fields['address_1']['hidden'] = true;
                    $fields['city']['hidden']      = true;
                    $fields['state']['hidden']     = true;
                    $fields['postcode']['hidden']  = true;
                }

                $fields['address_1']['required'] = false;
                $fields['city']['required']      = false;
                $fields['state']['required']     = false;
                $fields['postcode']['required']  = false;
            }
        }

        return $locale;
    }

    public function customizeCheckoutAddressFields( array $fields ): array
    {
        if ( SessionService::get()->isPickup() ) {
            if ( PluginSettings::get()->hideAddressFieldsOnPickup() ) {
                unset( $fields['address_1'] );
                unset( $fields['address_2'] );
                unset( $fields['city'] );
                unset( $fields['state'] );
                unset( $fields['postcode'] );
            } else {
                $fields['address_1']['required'] = false;
                $fields['address_2']['required'] = false;
                $fields['city']['required']      = false;
                $fields['state']['required']     = false;
                $fields['postcode']['required']  = false;
            }

            return $fields;
        }
        $city       = null;
        $address    = SessionService::get()->getAddress();
        $userInputs = SessionService::get()->getUserAddressInputs();

        if ( $address ) {
            if ( $address->suburb !== '' ) {
                $city = $address->suburb;
            }

            if ( $address->county !== '' ) {
                $city = $address->county;
            }

            if ( $address->city !== '' ) {
                $city = $address->city;
            }
        }

        if ( ! $city ) {
            $city = 'Neidentificat';
        }

        $fields['street_number'] = [
            'type'     => 'text',
            'label'    => 'Număr stradă',
            'priority' => 61,
            'default'  => $address->streetNumber ?? '',
            'value'    => $address->streetNumber ?? '',
        ];

        if ( $address ) {
            $fields['city']['custom_attributes'] = [
                'readonly' => 'readonly',
            ];
            $fields['city']['default']           = $city;
            $fields['city']['value']             = $city;
            unset( $fields['city']['autocomplete'] );

            $fields['address_1']['custom_attributes'] = [
                'readonly' => 'readonly',
            ];
            $fields['address_1']['default']           = $address->displayName;
            $fields['address_1']['value']             = $address->displayName;
            unset( $fields['address_1']['autocomplete'] );
            unset( $fields['address_2'] );
        }
        $fields['unit']      = [
            'type'     => 'text',
            'label'    => 'Bloc',
            'priority' => 62,
            'default'  => $userInputs->block ?? '',
            'value'    => $userInputs->block ?? '',
        ];
        $fields['staircase'] = [
            'type'     => 'text',
            'label'    => 'Scară',
            'priority' => 63,
            'default'  => $userInputs->entrance ?? '',
            'value'    => $userInputs->entrance ?? '',
        ];
        $fields['floor']     = [
            'type'     => 'text',
            'label'    => 'Etaj',
            'priority' => 64,
            'default'  => $userInputs->floor ?? '',
            'value'    => $userInputs->floor ?? '',
        ];
        $fields['apartment'] = [
            'type'     => 'text',
            'label'    => 'Apartament',
            'priority' => 65,
            'default'  => $userInputs->apartment ?? '',
            'value'    => $userInputs->apartment ?? '',
        ];

        return $fields;
    }

    private function getLocationNameFromAPI(): ?string
    {
        $res = makeHttpGet(
            "api/wp/getLocation/?uid={$this->defaultLocationUid}"
        );

        if ( isset( $res->payload->name ) ) {
            return $res->payload->name;
        }

        return null;
    }

    public function displayFieldsOnProductPage(): void
    {
        $this->displayProductCommentary();
    }

    private function displayProductCommentary(): void
    {
        woocommerce_form_field(
            'freya_sync_commentary',
            [
                'type'  => 'textarea',
                'class' => [ 'freya_sync_commentary', 'form-row-wide' ],
                'label' => __( 'Comentariu', 'woocommerce' ),
                'id'    => 'freya_sync_commentary',
            ]
        );
    }

    public function prepare_notices(): void
    {
        $html = $this->renderNeedAddressContent();

        if ( strlen( $html ) === 0 ) {
            ?>
            <div>Am întâmpinat o eroare cu crearea widget-ului Freya Sync.</div>
            <?php
        } else {
            echo $html;
        }
    }

    public function before_add_to_cart_form(): void
    {
        $product = wc_get_product();

        if ( ! $product ) {
            return;
        }

        $this->add_location_notice( $product );
        $this->add_returo_notice( $product );
    }

    private function add_location_notice( WC_Product $product ): void
    {
        if ( ! $product->meta_exists( 'location_ext' ) ) {
            return;
        }

        /** @var array<string, array{name: string, price: float}|false $ext */
        $ext = $product->get_meta( 'location_ext' );

        if ( ! $ext ) {
            return;
        }

        $names = array_map( function ( $item ) {
            return $item['name'];
        }, $ext );

        ?>
        <div class="fss-product-availability">
            Disponibil în locațiile: <strong><?php
                echo implode( ', ', $names ); ?></strong>
        </div>
        <?php
    }

    private function add_returo_notice( WC_Product $product ): void
    {
        if ( ! $product->meta_exists( 'returo_units' ) ) {
            return;
        }

        /** @var int $hasReturo */
        $hasReturo = intval( $product->get_meta( 'returo_units' ) );

        if ( $hasReturo === 0 ) {
            return;
        }

        $returoPrice = $hasReturo * 0.5;

        ?>
        <div class="fss-returo-notice">
            Prețul <strong>nu</strong> include garanția SGR (<?php
            echo sprintf( '%.2f lei', $returoPrice ); ?>)
        </div>
        <?php
    }

    public function addProductFieldsToCartItem(
        $cart_item_data,
        $product_id
    ): array {
        if ( isset( $_POST['freya_sync_commentary'] ) ) {
            $cart_item_data['freya_sync_commentary'] = sanitize_text_field(
                $_POST['freya_sync_commentary']
            );
        }

        return $cart_item_data;
    }

    public function addProductFieldsToOrderItem(
        $item,
        $cart_item_key,
        $values,
        $order
    ) {
        if ( isset( $values['freya_sync_commentary'] ) ) {
            $item->add_meta_data(
                '_freya_sync_commentary',
                $values['freya_sync_commentary'],
                true
            );
        }

        return $item;
    }

    public function validateCartOnSubmit( $fields, $errors ): void
    {
        if ( $this->noPolygons || SessionService::get()->isPickup() ) {
            return;
        }

        $userAddress = SessionService::get()->getUserAddress();

        if ( ! $userAddress || strlen( $userAddress ) === 0 ) {
            $errors->add(
                'validation',
                'Adresa de livrare nu este setată! <b style="cursor: pointer" class="address-modal-open">Te rugăm să selectezi o adresă de livrare</b>.'
            );
        }
    }

    /**
     * @hook woocommerce_checkout_create_order
     *
     * Rulează **la checkout**
     *
     * Din ceva motiv, save_meta_data() nu aplică datele extra, deci nu apelăm aici
     */
    public function order_created_old( WC_Order $order ): void
    {
        $this->add_meta_to_order( $order );
        $this->store_last_preferences_on_account();
    }

    /**
     * @hook woocommerce_store_api_checkout_update_order_meta
     *
     * Pentru interfața nouă cu blocks, rulează **când se intră pe pagina de checkout și după checkout**
     */
    public function order_created_new( WC_Order $order ): void
    {
        $this->add_meta_to_order( $order );
        $order->save_meta_data();
        $this->store_last_preferences_on_account();
    }

    private function add_meta_to_order( WC_Order $order ): void
    {
        if ( $order->get_meta( 'location_uid' ) && $order->get_meta( 'location_name' ) ) {
            return;
        }

        $locationName = SessionService::get()->getLocationName();
        $locationUid  = SessionService::get()->getLocationUid() ?? PluginSettings::get()->getDefaultLocationUid();

        if ( is_null( $locationName ) && $this->noPolygons ) {
            $locationName = $this->getLocationNameFromAPI();
            SessionService::get()->setLocationName( $locationName );
        }

        $items = $order->get_items();

        foreach ( $items as $item ) {
            $data = $item->get_data();

            if ( isset( $data['freya_sync_toppings'] ) ) {
                $item->update_meta_data(
                    'freya_sync_toppings',
                    $data['freya_sync_toppings']
                );
                $item->save();
                $item->save_meta_data();
            }
        }

        $address = SessionService::get()->getAddress() ?? null;

        if ( isset( $address ) ) {
            $order->update_meta_data( 'freya-sync-address-id', $address->id );
            $order->update_meta_data(
                'freya-sync-address-type',
                $address->type
            );
        }

        if ( ! isset( $locationName ) || ! isset( $locationUid ) ) {
            error_log( sprintf(
                'Nu am putut seta locația pentru comanda %d. Detalii: locationName: %s, locationUid: %s. Sesiune: %s',
                $order->get_id(),
                $locationName ?? '-',
                $locationUid ?? '-',
                json_encode( $_SESSION ?? [] )
            ) );

            $location = $this->getFetchedLocationIfOne();

            if ( $location === null ) {
                $order->update_meta_data(
                    'freya-sync-error',
                    'Nu am putut asocia aceasta comandă unei locații'
                );
                $order->update_meta_data( 'freya-sync-processed', 'false' );

                return;
            } else {
                if ( !isset( $locationUid ) ) {
                    $locationUid = $location->uid;
                    SessionService::get()->setLocationUid( $locationUid );
                }

                if ( !isset( $locationName ) ) {
                    $locationName = $location->name;
                    SessionService::get()->setLocationName( $locationUid );
                }
            }
        }

        $order->update_meta_data( 'location_uid', $locationUid );
        $order->update_meta_data( 'location_name', $locationName );
        $order->update_meta_data( 'freya-sync-uid', '' );
        $order->update_meta_data( 'freya-order-id', '' );
        $order->update_meta_data( 'freya-sync-error', '' );
        $order->update_meta_data( 'freya-sync-processed', '' );
    }

    private function getFetchedLocationIfOne(): ?Location
    {
        $locations = SessionService::get()->getFetchedLocations();

        return count( $locations ) === 1
            ? $locations[0]
            : null;
    }

    private function store_last_preferences_on_account(): void
    {
        $store = new AccountStore();

        if ( ! $store->is_available() || $this->noPolygons ) {
            return;
        }

        $store->put( 'location_uid', SessionService::get()->getLocationUid() );
        $store->put(
            'location_name',
            SessionService::get()->getLocationName()
        );

        if ( SessionService::get()->isPickup() ) {
            $store->put( 'pickup', true );
            $store->forget( 'address' );
            $store->forget( 'user_address_inputs' );
        } elseif ( $address = SessionService::get()->getAddress() ) {
            $store->put( 'address', serialize( $address ) );
            $store->forget( 'pickup' );

            if ( $extra_inputs = SessionService::get()->getUserAddressInputs() ) {
                $store->put( 'user_address_inputs', $extra_inputs );
            } else {
                $store->forget( 'user_address_inputs' );
            }
        }
    }

    public function ajaxClearSession(): void
    {
        check_ajax_referer( 'wp_rest' );
        $this->destroySession();
        wp_send_json_success();
    }

    public function registerShippingMethod( $methods ): array
    {
        $methods['fs_shipping_method'] = new FsShippingMethod();
        $methods['fs_pickup_method']   = new FsPickupMethod();

        return $methods;
    }

    public function modify_product_price(
        string $price,
        WC_Product $product
    ): string {
        if ( is_admin() ) {
            return $price;
        }

        $locationUid = SessionService::get()->getLocationUid()
                       ?? PluginSettings::get()->getDefaultLocationUid();

        if ( is_null( $locationUid ) ) {
            return $price;
        }

        // Call in edit context to not recurse with hooks
        if ( $product->get_regular_price( 'edit' ) === $product->get_price( 'edit' ) ) {
            return $this->modify_product_regular_price( $price, $product );
        }

        return $price;
    }

    public function modify_product_regular_price(
        string $price,
        WC_Product $product
    ): string {
        if ( is_admin() ) {
            return $price;
        }

        $locationUid = SessionService::get()->getLocationUid()
                       ?? PluginSettings::get()->getDefaultLocationUid();

        if ( is_null( $locationUid ) ) {
            return $price;
        }

        /** @var array<string, array{name: string, price: float}>|false $ext */
        $ext = $product->get_meta( 'location_ext' );

        if ( ! $ext ) {
            return $price;
        }

        // Dacă avem doar o locație nu are sens să facem acest override
        if ( count( $ext ) <= 1 ) {
            return $price;
        }

        foreach ( $ext as $uid => $value ) {
            if ( $uid !== $locationUid ) {
                continue;
            }

            return wc_float_to_string( (float) $value['price'] );
        }

        return $price;
    }

    public function breadcrumb(): void
    {
        if ( ! SessionService::get()->flashNeedLocation() ) {
            return;
        }

        echo $this->renderNoAddress();
        SessionService::get()->setFlashNeedLocation( false );
    }

    /**
     * @filter woocommerce_cart_item_name
     */
    public function display_product_data_in_cart(
        string $name,
        array $cart_item,
        string $cart_item_key
    ): string {
        $description = $cart_item['freya_sync_commentary'] ?? null;

        if ( empty( $description ) ) {
            return $name;
        }

        $name .= <<<HTML
                <div class="fss-comentary">Observații: {$description}</div>
            HTML;

        return $name;
    }

    /**
     * @filter woocommerce_order_item_meta_start
     */
    public function display_product_data_on_thank_you(
        int $item_id,
        \WC_Order_Item_Product $item,
        WC_Order $order
    ): void {
        $meta = $item->get_meta( '_freya_sync_commentary' );

        if ( ! $meta ) {
            return;
        }

        ?>
        <div class="fss-commentary">Observații: <?php
            echo $meta; ?></div>
        <?php
    }

    public function init(): void
    {
        if ( isset( $_GET['redirect-payload'] ) ) {
            AddressService::get()->setLocationSettingsMultisite(
                $_GET['redirect-payload']
            );
        }

        if ( ! $this->noPolygons ) {
            add_action(
                'wp_ajax_nopriv_cart_clear_session',
                [ $this, 'ajaxClearSession' ],
                1
            );
            add_action(
                'wp_ajax_cart_clear_session',
                [ $this, 'ajaxClearSession' ],
                1
            );

            // Create public route for address modal dismissed
            add_action(
                'wp_ajax_nopriv_cart_service_service_modal_dismissed',
                [ $this, 'setModalDismissed' ],
                1
            );
            add_action(
                'wp_ajax_cart_service_service_modal_dismissed',
                [ $this, 'setModalDismissed' ],
                1
            );

            // Validare coș (fără ajax)
            add_filter(
                'woocommerce_add_to_cart_validation',
                [ $this, 'validate_cart_item_old' ],
                99,
                2
            );
            // Validare coș (cu ajax) - woocommerce >= 7.1
            add_filter(
                'woocommerce_store_api_validate_add_to_cart',
                [ $this, 'validate_cart_item_new' ]
            );
            add_action(
                'woocommerce_after_cart_item_quantity_update',
                [ $this, 'validate_cart_item_qty_update' ],
                10,
                4
            );

            // Add extra taxes to cart
            add_action(
                'woocommerce_cart_calculate_fees',
                [ $this, 'setMinimOrderValue' ],
                1
            );

            // Register shipping method
            add_filter(
                'woocommerce_shipping_methods',
                [ $this, 'registerShippingMethod' ],
                1,
                1
            );

            // Hook on edit billing address
            add_filter(
                'woocommerce_checkout_fields',
                [ $this, 'onWoocommerceBillingFields' ],
                10,
                2
            );
            add_filter(
                'woocommerce_get_country_locale',
                [ $this, 'edit_blocks_checkout_fields' ],
                99
            );
            add_filter(
                'woocommerce_default_address_fields',
                [ $this, 'customizeCheckoutAddressFields' ],
                99
            );

            add_filter(
                'woocommerce_after_checkout_validation',
                [ $this, 'validateCartOnSubmit' ],
                10,
                2
            );

            add_action(
                'woocommerce_before_shop_loop',
                [ $this, 'prepare_notices' ],
                10
            );
            add_action(
                'woocommerce_before_single_product',
                [ $this, 'prepare_notices' ],
                99
            );
            add_action(
                'woocommerce_before_add_to_cart_form',
                [ $this, 'before_add_to_cart_form' ],
                10
            );

            add_filter( 'pre_get_posts', function ( WP_Query $query ) {
                if ( ! is_admin() && ( is_shop() || is_search() || is_product_category() ) ) {
                    $this->filterProductsByLocation( $query );
                }
            } );

            add_action( 'template_redirect', function () {
                if ( $this->needToAskAddressOnLoad && $this->isRestApi === false ) {
                    ob_start( [ $this, 'finalHtmlResponse' ] );
                }
            } );
        }

        add_filter(
            'woocommerce_cart_item_name',
            [ $this, 'display_product_data_in_cart' ],
            10,
            3
        );
        add_filter(
            'woocommerce_order_item_meta_start',
            [ $this, 'display_product_data_on_thank_you' ],
            10,
            3
        );

        // Add extra fields on product page
        add_action(
            'woocommerce_before_add_to_cart_button',
            [ $this, 'displayFieldsOnProductPage' ]
        );
        add_filter(
            'woocommerce_add_cart_item_data',
            [ $this, 'addProductFieldsToCartItem' ],
            11,
            2
        );
        add_filter(
            'woocommerce_checkout_create_order_line_item',
            [ $this, 'addProductFieldsToOrderItem' ],
            11,
            4
        );

        add_action(
            'woocommerce_cart_loaded_from_session',
            [ $this, 'check_cart_item_locations' ],
            10
        );
        // Detect if is a rest call api
        add_action( 'rest_api_init', [ $this, 'initRestApi' ] );

        // Creare comandă - interfață veche și cea nouă bazată pe blocks
        add_filter(
            'woocommerce_checkout_create_order',
            [ $this, 'order_created_old' ]
        );
        add_filter(
            'woocommerce_store_api_checkout_update_order_meta',
            [ $this, 'order_created_new' ]
        );

        // Action on order is placed - unset session
        add_action( 'woocommerce_thankyou', [ $this, 'onOrderPlaced' ], 10, 1 );

        add_action( 'woocommerce_breadcrumb', [ $this, 'breadcrumb' ] );

        add_action(
            'woocommerce_product_get_price',
            [ $this, 'modify_product_price' ],
            10,
            2
        );
        add_action(
            'woocommerce_product_get_regular_price',
            [ $this, 'modify_product_regular_price' ],
            10,
            2
        );
    }
}
