<?php
/**
 * Copyright © Simplyin. All rights reserved.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Service;

use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\MessageQueue\PublisherInterface;
use Psr\Log\LoggerInterface;

/**
 * Finalizes a placed Magento order
 *
 * Loads the placed order, persists SimplyIN payment info on it,
 * triggers async SimplyIN syncs and builds the success response.
 */
class PlaceOrderFinalizer
{
    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var PublisherInterface
     */
    private $publisher;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * Constructor
     *
     * @param OrderRepositoryInterface $orderRepository
     * @param PublisherInterface $publisher
     * @param LoggerInterface $logger
     */
    public function __construct(
        OrderRepositoryInterface $orderRepository,
        PublisherInterface $publisher,
        LoggerInterface $logger
    ) {
        $this->orderRepository = $orderRepository;
        $this->publisher = $publisher;
        $this->logger = $logger;
    }

    /**
     * Load placed order, update payment with SimplyIN info, trigger async syncs and build success response
     *
     * @param array $paymentInfo
     * @param array $data
     * @param mixed $orderId
     * @param mixed $quoteId
     * @param \Magento\Framework\Controller\Result\Json $result
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function finalizeOrder($paymentInfo, $data, $orderId, $quoteId, $result)
    {
        // Load the created order
        $order = $this->orderRepository->get($orderId);

        // Update order payment with SimplyIN info
        $orderPayment = $order->getPayment();
        foreach ($paymentInfo as $key => $value) {
            $orderPayment->setAdditionalInformation($key, $value);
        }
        $this->orderRepository->save($order);

        // Update SimplyIN order status asynchronously (non-blocking)
        $simplyinOrderId = $data['simplyinOrderId'] ?? '';
        $authToken = $data['authToken'] ?? '';
        if ($simplyinOrderId && $authToken) {
            $this->publishOrderStatusUpdate($simplyinOrderId, $order->getIncrementId(), $authToken);
        }

        // Publish post-placement sync asynchronously
        $this->publishPostPlacementSync((int)$orderId, $simplyinOrderId);

        $this->logger->info('SimplyIN: Magento order created successfully', [
            'order_id' => $orderId,
            'increment_id' => $order->getIncrementId(),
            'quote_id' => $quoteId,
            'simplyin_order_id' => $simplyinOrderId,
            'simplyin_payment_id' => $paymentInfo['simplyin_payment_id'] ?? ''
        ]);

        return $result->setData([
            'success' => true,
            'orderId' => $orderId,
            'incrementId' => $order->getIncrementId(),
            'message' => __('Magento order created successfully')
        ]);
    }

    /**
     * Publish order status update to async queue
     *
     * @param string $simplyinOrderId SimplyIN order ID
     * @param string $magentoOrderId Magento order increment ID
     * @param string $authToken Auth token
     */
    private function publishOrderStatusUpdate(string $simplyinOrderId, string $magentoOrderId, string $authToken): void
    {
        try {
            $message = json_encode([
                'simplyinOrderId' => $simplyinOrderId,
                'magentoOrderId' => $magentoOrderId,
                'authToken' => $authToken,
                'status' => 'CONFIRMED'
            ], JSON_THROW_ON_ERROR);

            $this->publisher->publish('simplyin.order.status.update', $message);

            $this->logger->info('SimplyIN: Published order status update to queue', [
                'simplyin_order_id' => $simplyinOrderId,
                'magento_order_id' => $magentoOrderId
            ]);
        } catch (\Exception $e) {
            // If queue publish fails, log but don't block checkout
            $this->logger->error('SimplyIN: Failed to publish order status update', [
                'simplyin_order_id' => $simplyinOrderId,
                'error' => $e->getMessage()
            ]);
        }
    }

    /**
     * Publish post-placement sync to async queue
     *
     * @param int $orderId Magento order entity ID
     * @param string $simplyinOrderId SimplyIN order ID
     */
    private function publishPostPlacementSync(int $orderId, string $simplyinOrderId): void
    {
        try {
            $message = json_encode([
                'orderId' => $orderId,
                'simplyinOrderId' => $simplyinOrderId
            ], JSON_THROW_ON_ERROR);

            $this->publisher->publish('simplyin.order.sync.post_placement', $message);
        } catch (\Exception $e) {
            $this->logger->error('SimplyIN: Failed to publish post-placement sync', [
                'order_id' => $orderId,
                'error' => $e->getMessage()
            ]);
        }
    }
}
