<?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 Customer;
use Order;
use Simplyin;
use SimplyIn\Ajax\AjaxActionInterface;
use SimplyIn\Ajax\AjaxRequest;
use SimplyIn\Ajax\Service\CheckoutSessionService;
use SimplyIn\Api\SimplyInApiClient;
use SimplyIn\Session\SimplyInSessionInterface;
use SimplyInEmailCache;
use SimplyInOrder;
use SimplyInOrderSync;

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

final class PlaceOrderHandler implements AjaxActionInterface
{
    public function __construct(
        private readonly SimplyInApiClient $api,
        private readonly Simplyin $module,
        private readonly SimplyInSessionInterface $session,
        private readonly CheckoutSessionService $checkoutSession,
    ) {
    }

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

    public function execute(AjaxRequest $request): array
    {
        $idCart = $request->getInt('id_cart');
        $orderToken = $request->getString('order_token');

        if ($orderToken !== $this->module->getOrderToken($idCart)) {
            return ['success' => false, 'error' => $this->module->l('Invalid order token', 'ajax')];
        }

        $order = Order::getByCartId($idCart);
        if (!$order instanceof Order) {
            return ['success' => false, 'error' => $this->module->l('Invalid order', 'ajax')];
        }

        $authToken = $this->checkoutSession->getAuthToken();
        $newAccountPhone = (string) $this->session->get('new_account_phone', '');

        $result = [];
        if ($authToken) {
            $result = $this->createOrderWithoutAccount($order, $authToken);
            $this->session->set('simplyin_auth_token', $authToken);
        } elseif ($newAccountPhone !== '' && $newAccountPhone !== '0') {
            $result = $this->createOrderAndAccount($order, $newAccountPhone);
        } else {
            $this->session->clear();

            return ['success' => false, 'error' => $this->module->l('Invalid order', 'ajax')];
        }

        $this->checkoutSession->clearPsAddressIds();

        if (isset($result['createdOrder']['_id'])) {
            $object = SimplyInOrder::getByIdOrder((int) $order->id);

            if ($object instanceof SimplyInOrder) {
                $object->simplyin_id = (string) $result['createdOrder']['_id'];
                $object->save();
            }
        }

        $this->session->clear();

        return ['success' => true, 'result' => $result];
    }

    /**
     * @return array<string, mixed>
     */
    private function createOrderWithoutAccount(Order $order, string $authToken): array
    {
        $orderData = SimplyInOrderSync::getOrderData((int) $order->id);
        $orderData['newOrderData']['placedDuringAccountCreation'] = false;
        unset($orderData['newAccountData']);

        $result = $this->api->apiCall($orderData, 'POST', 'checkout/createOrderWithoutAccount', $authToken);

        return is_array($result) ? $result : [];
    }

    /**
     * @return array<string, mixed>
     */
    private function createOrderAndAccount(Order $order, string $phoneNumber): array
    {
        $customer = new Customer((int) $order->id_customer);
        SimplyInEmailCache::clearCacheByEmail((string) $customer->email);

        $orderData = SimplyInOrderSync::getOrderData((int) $order->id);
        $orderData['newOrderData']['placedDuringAccountCreation'] = true;
        $orderData['newAccountData'] ??= [];
        $orderData['newAccountData']['email'] = (string) $customer->email;
        $orderData['newAccountData']['phoneNumber'] = $phoneNumber;

        $result = $this->api->apiCall($orderData, 'POST', 'checkout/createOrderAndAccount');

        return is_array($result) ? $result : [];
    }
}
