<?php

/**
 * Copyright 2024-2025 Simply.IN Sp. z o.o.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the EUPL-1.2 or later.
 * You may not use this work except in compliance with the Licence.
 *
 * Copy of the Licence is available at:
 * https://joinup.ec.europa.eu/software/page/eupl
 * It is bundled with this package in the file LICENSE.txt
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an as is basis,
 * without warranties or conditions of any kind, either express or implied.
 * Check the Licence for the specific language governing permissions
 * and limitations under the License.
 *
 * @author   Simply.IN Sp. z o.o.
 * @copyright 2024-2025 Simply.IN Sp. z o.o.
 * @license   https://joinup.ec.europa.eu/software/page/eupl
 */

declare(strict_types=1);

namespace SimplyIn\Ajax\Handler;

use Context;
use Simplyin;
use SimplyIn\Ajax\AjaxActionInterface;
use SimplyIn\Ajax\AjaxRequest;
use SimplyIn\Ajax\Service\AddressService;
use SimplyIn\Ajax\Service\CarrierPointService;
use SimplyIn\Ajax\Service\CheckoutSessionService;
use SimplyIn\Ajax\Service\SimplyInAddressService;

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

final class SelectAddressHandler implements AjaxActionInterface
{
    public function __construct(
        private readonly Context $context,
        private readonly Simplyin $module,
        private readonly SimplyInAddressService $simplyInAddress,
        private readonly AddressService $addressService,
        private readonly CheckoutSessionService $checkoutSession,
        private readonly CarrierPointService $carrierPointService,
    ) {
    }

    public function name(): string
    {
        return 'selectAddress';
    }

    public function execute(AjaxRequest $request): array
    {
        $invoiceAddressId = $request->getString('invoice_address');
        $deliveryAddressId = $request->getString('delivery_address');
        if ($deliveryAddressId === '') {
            $deliveryAddressId = $invoiceAddressId;
        }
        $selectedPointId = $request->getString('selected_point');
        $serviceType = $request->getString('service_type');

        $this->checkoutSession->storeSelection(
            $invoiceAddressId,
            $deliveryAddressId,
            $selectedPointId,
            $serviceType,
        );

        $authToken = $this->checkoutSession->getAuthToken();
        $userData = $this->simplyInAddress->userData($authToken ?: null);
        $customerId = (int) ($this->context->customer->id ?? 0);

        $invoiceAddress = $this->simplyInAddress->findInUserData($userData, $invoiceAddressId, 'billingAddresses');
        $phone = $this->simplyInAddress->getPhoneNumber($userData);

        $psIdAddressInvoice = $invoiceAddress['address']
            ? $this->addressService->findExistingAddressId($customerId, (array) $invoiceAddress['address'])
            : false;
        if (!$psIdAddressInvoice && $invoiceAddress['address']) {
            $psIdAddressInvoice = $this->addressService->createPsAddress($customerId, (array) $invoiceAddress['address'], $phone);
        }

        $deliveryAddress = $invoiceAddressId !== $deliveryAddressId
            ? $this->simplyInAddress->findInUserData($userData, $deliveryAddressId, 'shippingAddresses')
            : $invoiceAddress;

        $psIdAddressDelivery = $deliveryAddress['address']
            ? $this->addressService->findExistingAddressId($customerId, (array) $deliveryAddress['address'])
            : false;
        if (!$psIdAddressDelivery && $deliveryAddress['address']) {
            $psIdAddressDelivery = $this->addressService->createPsAddress($customerId, (array) $deliveryAddress['address'], $phone);
        }

        if ($this->context->customer !== null && $this->context->customer->isGuest() && $psIdAddressInvoice && $psIdAddressDelivery) {
            $this->addressService->deleteOtherGuestAddresses($customerId, (int) $psIdAddressInvoice, (int) $psIdAddressDelivery);
        }

        $this->checkoutSession->storePsAddressIds((int) $psIdAddressDelivery, (int) $psIdAddressInvoice);

        $cart = $this->context->cart;
        if ($cart !== null && $cart->id) {
            $cart->id_address_delivery = (int) $psIdAddressDelivery;
            $cart->id_address_invoice = (int) $psIdAddressInvoice;
            $cart->delivery_option = (string) json_encode([
                (int) $cart->id_address_delivery => ((int) $cart->id_carrier) . ',',
            ]);
            $cart->update();
            $this->addressService->updateDeliveryAddressOnCartLines((int) $cart->id_address_delivery, (int) $cart->id);

            if ($selectedPointId !== '') {
                $point = $this->simplyInAddress->findInUserData($userData, $selectedPointId);
                if (is_array($point['address'])) {
                    $this->carrierPointService->selectPoint((int) $cart->id, (array) $point['address']);
                }
            } else {
                $this->carrierPointService->clearPoint((int) $cart->id);
            }
        }

        $checkoutSessionData = $this->module->getCheckoutSessionData();
        $this->module->upgradeSessionData($checkoutSessionData, false);

        return [
            'success' => true,
            'warnings' => [],
            'redirect' => $this->needsRedirect(),
        ];
    }

    private function needsRedirect(): bool
    {
        if ($this->module->getOPC() === 'thecheckout') {
            return true;
        }
        $customer = $this->context->customer;

        return $customer !== null && !$customer->isGuest();
    }
}
