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

namespace Simplyin\Payment\Controller\Api;

use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Psr\Log\LoggerInterface;

/**
 * Update Order Payment Controller
 *
 * Updates Magento order with SimplyIN payment information after order is created.
 * Called by frontend after Magento order is placed to store payment details.
 */
class UpdateOrderPayment implements HttpPostActionInterface, CsrfAwareActionInterface
{
    use CsrfAwareApiTrait;

    /**
     * @var JsonFactory
     */
    private $resultJsonFactory;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

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

    /**
     * @var RequestInterface
     */
    private $request;

    /**
     * Constructor
     *
     * @param JsonFactory $resultJsonFactory
     * @param OrderRepositoryInterface $orderRepository
     * @param LoggerInterface $logger
     * @param RequestInterface $request
     */
    public function __construct(
        JsonFactory $resultJsonFactory,
        OrderRepositoryInterface $orderRepository,
        LoggerInterface $logger,
        RequestInterface $request
    ) {
        $this->resultJsonFactory = $resultJsonFactory;
        $this->orderRepository = $orderRepository;
        $this->logger = $logger;
        $this->request = $request;
    }

    /**
     * Execute update order payment
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();

        try {
            $content = $this->request->getContent();
            $data = json_decode($content, true);

            $orderId = $data['orderId'] ?? null;
            $paymentInfo = $data['paymentInfo'] ?? [];
            $simplyinOrderId = $data['simplyinOrderId'] ?? '';

            if (!$orderId) {
                return $result->setData([
                    'success' => false,
                    'message' => __('Order ID is required')
                ]);
            }

            $this->logger->info('SimplyIN UpdateOrderPayment: Updating order', [
                'orderId' => $orderId,
                'simplyinOrderId' => $simplyinOrderId,
                'hasPaymentInfo' => !empty($paymentInfo)
            ]);

            try {
                $order = $this->orderRepository->get($orderId);
                $payment = $order->getPayment();

                if ($payment) {
                    return $this->applyPaymentInfoAndSave(
                        $result,
                        $order,
                        $payment,
                        $paymentInfo,
                        $simplyinOrderId,
                        $orderId
                    );
                } else {
                    $this->logger->warning('SimplyIN UpdateOrderPayment: No payment object found for order', [
                        'orderId' => $orderId
                    ]);

                    return $result->setData([
                        'success' => false,
                        'message' => __('No payment found for order')
                    ]);
                }
            } catch (\Exception $e) {
                $this->logger->error('SimplyIN UpdateOrderPayment: Failed to update order', [
                    'orderId' => $orderId,
                    'error' => $e->getMessage()
                ]);

                return $result->setData([
                    'success' => false,
                    'message' => __('Failed to update order. Please try again.')
                ]);
            }

        } catch (\Exception $e) {
            $this->logger->error('SimplyIN UpdateOrderPayment exception: ' . $e->getMessage());

            return $result->setData([
                'success' => false,
                'message' => __('An unexpected error occurred. Please try again.')
            ]);
        }
    }

    /**
     * Apply SimplyIN payment information to the payment, save the order and build the success response.
     *
     * @param \Magento\Framework\Controller\Result\Json $result
     * @param \Magento\Sales\Api\Data\OrderInterface $order
     * @param \Magento\Sales\Api\Data\OrderPaymentInterface $payment
     * @param array $paymentInfo
     * @param string $simplyinOrderId
     * @param mixed $orderId
     * @return \Magento\Framework\Controller\Result\Json
     */
    private function applyPaymentInfoAndSave($result, $order, $payment, $paymentInfo, $simplyinOrderId, $orderId)
    {
        // Store SimplyIN payment information (copied from paymentInfo when non-empty)
        $this->copyPaymentInfoFields($payment, $paymentInfo);

        if (!empty($simplyinOrderId)) {
            $payment->setAdditionalInformation('simplyin_order_id', $simplyinOrderId);
        }
        if (isset($paymentInfo['simplyin_redirect_iframe_allowed'])) {
            $payment->setAdditionalInformation('simplyin_redirect_iframe_allowed', $paymentInfo['simplyin_redirect_iframe_allowed']);
        }

        // Flag for payment-only mode (no SimplyIN order created)
        if (empty($simplyinOrderId)) {
            $payment->setAdditionalInformation('simplyin_payment_only', true);
        }

        $this->orderRepository->save($order);

        $this->logger->info('SimplyIN UpdateOrderPayment: Payment info stored successfully', [
            'orderId' => $orderId,
            'incrementId' => $order->getIncrementId()
        ]);

        return $result->setData([
            'success' => true,
            'message' => __('Order payment info updated successfully')
        ]);
    }

    /**
     * Copy non-empty SimplyIN payment fields from the payload onto the payment.
     *
     * @param \Magento\Sales\Api\Data\OrderPaymentInterface $payment
     * @param array $paymentInfo
     * @return void
     */
    private function copyPaymentInfoFields($payment, array $paymentInfo)
    {
        $fields = [
            'simplyin_payment_id',
            'simplyin_payment_status',
            'simplyin_provider_payment_id',
            'simplyin_redirect_url',
            'simplyin_registered_at',
        ];

        foreach ($fields as $field) {
            if (!empty($paymentInfo[$field])) {
                $payment->setAdditionalInformation($field, $paymentInfo[$field]);
            }
        }
    }
}
