<?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\Checkout;

use Order;
use SimplyIn\Session\SimplyInSessionInterface;

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

final class OrderPlacementService
{
    public function __construct(
        private readonly SimplyInSessionInterface $session,
        private readonly CheckoutApiInterface $api,
        private readonly OrderDataFetcherInterface $orderData,
        private readonly CustomerEmailProviderInterface $customers,
        private readonly EmailCacheInterface $emailCache,
    ) {
    }

    public function placeOrder(Order $order): OrderPlacementResult
    {
        $authToken = (string) ($this->session->get('simplyin_auth_token', false) ?: '');
        $newAccountPhone = (string) ($this->session->get('new_account_phone', false) ?: '');

        if ($authToken !== '') {
            $this->createOrderWithoutAccount($order, $authToken);
            $this->session->set('simplyin_auth_token', $authToken);

            return new OrderPlacementResult(false, $authToken);
        }

        if ($newAccountPhone !== '') {
            $response = $this->createOrderAndAccount($order);
            $newToken = (string) ($response['authToken'] ?? '');
            $this->session->set('simplyin_auth_token', $newToken);

            $email = $this->customers->emailFor((int) $order->id_customer);
            $this->session->set('simplyin_email', $email);
            $this->session->unset('new_account_phone');

            return new OrderPlacementResult(true, $newToken);
        }

        return new OrderPlacementResult(false, '');
    }

    private function createOrderWithoutAccount(Order $order, string $authToken): void
    {
        $orderData = $this->orderData->fetch((int) $order->id);
        if (isset($orderData['newOrderData']) && is_array($orderData['newOrderData'])) {
            $orderData['newOrderData']['placedDuringAccountCreation'] = false;
        }
        unset($orderData['newAccountData']);

        $this->api->createOrderWithoutAccount($orderData, $authToken);
    }

    /**
     * @return array<string, mixed>
     */
    private function createOrderAndAccount(Order $order): array
    {
        $email = $this->customers->emailFor((int) $order->id_customer);
        $this->emailCache->clear($email);

        $orderData = $this->orderData->fetch((int) $order->id);
        if (isset($orderData['newOrderData']) && is_array($orderData['newOrderData'])) {
            $orderData['newOrderData']['placedDuringAccountCreation'] = true;
        }

        return $this->api->createOrderAndAccount($orderData) ?? [];
    }
}
