<?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\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Quote\Model\QuoteIdMaskFactory;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Checkout\Model\Session as CheckoutSession;
use Simplyin\Payment\Service\PlaceOrderFinalizer;
use Psr\Log\LoggerInterface;

/**
 * Place Magento Order controller
 *
 * Creates Magento order first before SimplyIN order
 * Handles payment completion data storage
 */
class PlaceMagentoOrder implements HttpPostActionInterface, CsrfAwareActionInterface
{
    use CsrfAwareApiTrait;

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

    /**
     * @var CartRepositoryInterface
     */
    private $quoteRepository;

    /**
     * @var CartManagementInterface
     */
    private $cartManagement;

    /**
     * @var QuoteIdMaskFactory
     */
    private $quoteIdMaskFactory;

    /**
     * @var PlaceOrderFinalizer
     */
    private $placeOrderFinalizer;

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

    /**
     * @var CustomerSession
     */
    private $customerSession;

    /**
     * @var CheckoutSession
     */
    private $checkoutSession;

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

    /**
     * Constructor
     *
     * @param JsonFactory $resultJsonFactory
     * @param CartRepositoryInterface $quoteRepository
     * @param CartManagementInterface $cartManagement
     * @param QuoteIdMaskFactory $quoteIdMaskFactory
     * @param PlaceOrderFinalizer $placeOrderFinalizer
     * @param LoggerInterface $logger
     * @param CustomerSession $customerSession
     * @param CheckoutSession $checkoutSession
     * @param RequestInterface $request
     */
    public function __construct(
        JsonFactory $resultJsonFactory,
        CartRepositoryInterface $quoteRepository,
        CartManagementInterface $cartManagement,
        QuoteIdMaskFactory $quoteIdMaskFactory,
        PlaceOrderFinalizer $placeOrderFinalizer,
        LoggerInterface $logger,
        CustomerSession $customerSession,
        CheckoutSession $checkoutSession,
        RequestInterface $request
    ) {
        $this->resultJsonFactory = $resultJsonFactory;
        $this->quoteRepository = $quoteRepository;
        $this->cartManagement = $cartManagement;
        $this->quoteIdMaskFactory = $quoteIdMaskFactory;
        $this->placeOrderFinalizer = $placeOrderFinalizer;
        $this->logger = $logger;
        $this->customerSession = $customerSession;
        $this->checkoutSession = $checkoutSession;
        $this->request = $request;
    }

    /**
     * Execute place Magento order action
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        
        try {
            $data = json_decode($this->request->getContent(), true);
            $quoteId = $data['quoteId'] ?? null;

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

            // Handle masked quote ID for guest customers
            $quoteId = $this->resolveQuoteId($quoteId);

            // Load quote
            $quote = $this->quoteRepository->get($quoteId);

            if (!$quote->getId()) {
                return $result->setData([
                    'success' => false,
                    'message' => __('Quote not found')
                ]);
            }

            // Verify cart ownership: logged-in customer must own the cart
            $ownershipError = $this->verifyCartOwnership($quote, $quoteId, $result);
            if ($ownershipError !== null) {
                return $ownershipError;
            }

            // Check if quote is active
            if (!$quote->getIsActive()) {
                return $result->setData([
                    'success' => false,
                    'message' => __('Quote is no longer active')
                ]);
            }

            // Set payment method to simplyin_payment
            $payment = $quote->getPayment();
            $payment->setMethod('simplyin_payment');

            // Store SimplyIN payment information in payment additional_information
            $paymentInfo = $this->extractPaymentInfo($data);
            foreach ($paymentInfo as $key => $value) {
                $payment->setAdditionalInformation($key, $value);
            }

            $this->quoteRepository->save($quote);

            // Place order
            $orderId = $this->cartManagement->placeOrder($quote->getId());

            if (!$orderId) {
                return $result->setData([
                    'success' => false,
                    'message' => __('Failed to create Magento order')
                ]);
            }

            return $this->placeOrderFinalizer->finalizeOrder($paymentInfo, $data, $orderId, $quoteId, $result);

        } catch (\Exception $e) {
            $this->logger->error('SimplyIN PlaceMagentoOrder Error: ' . $e->getMessage());
            return $result->setData([
                'success' => false,
                'message' => __('An unexpected error occurred. Please try again.')
            ]);
        }
    }

    /**
     * Extract payment information from request data
     *
     * @param array $data Request data
     * @return array Payment information for additional_information
     */
    private function extractPaymentInfo($data)
    {
        $paymentInfo = [];

        // SimplyIN order and payment IDs
        if (!empty($data['simplyinOrderId'])) {
            $paymentInfo['simplyin_order_id'] = $data['simplyinOrderId'];
        }
        if (!empty($data['simplyinPaymentId'])) {
            $paymentInfo['simplyin_payment_id'] = $data['simplyinPaymentId'];
        }
        if (!empty($data['providerPaymentId'])) {
            $paymentInfo['simplyin_provider_payment_id'] = $data['providerPaymentId'];
        }

        // Payment status
        if (!empty($data['paymentStatus'])) {
            $paymentInfo['simplyin_payment_status'] = $data['paymentStatus'];
        }

        $paymentInfo = $this->extractPaymentDisplayInfo($data, $paymentInfo);

        return $paymentInfo;
    }

    /**
     * Extract 3D Secure, card and payment-type display information from request data
     *
     * @param array $data Request data
     * @param array $paymentInfo Payment information accumulated so far
     * @return array Payment information for additional_information
     */
    private function extractPaymentDisplayInfo($data, $paymentInfo)
    {
        // 3D Secure info
        if (!empty($data['redirectUrl'])) {
            $paymentInfo['simplyin_redirect_url'] = $data['redirectUrl'];
        }
        if (isset($data['redirectIframeAllowed'])) {
            $paymentInfo['simplyin_redirect_iframe_allowed'] = $data['redirectIframeAllowed'] ? '1' : '0';
        }

        // Card info (for display purposes only)
        if (!empty($data['cardLast4'])) {
            $paymentInfo['simplyin_card_last4'] = $data['cardLast4'];
        }
        if (!empty($data['cardBrand'])) {
            $paymentInfo['simplyin_card_brand'] = $data['cardBrand'];
        }

        // Payment method type
        if (!empty($data['paymentType'])) {
            $paymentInfo['simplyin_payment_type'] = $data['paymentType'];
        }

        return $paymentInfo;
    }

    /**
     * Resolve masked quote ID to actual ID for guest customers
     *
     * @param mixed $quoteId
     * @return mixed
     */
    private function resolveQuoteId($quoteId)
    {
        // Handle masked quote ID for guest customers
        if (!is_numeric($quoteId)) {
            $quoteIdMask = $this->quoteIdMaskFactory->create()->load($quoteId, 'masked_id');
            if ($quoteIdMask->getQuoteId()) {
                $quoteId = $quoteIdMask->getQuoteId();
                $this->logger->info('SimplyIN: Converted masked quote ID to actual ID: ' . $quoteId);
            }
        }

        return $quoteId;
    }

    /**
     * Verify cart ownership for logged-in customers and guests
     *
     * @param \Magento\Quote\Api\Data\CartInterface $quote
     * @param mixed $quoteId
     * @param \Magento\Framework\Controller\Result\Json $result
     * @return \Magento\Framework\Controller\Result\Json|null Error result or null when ownership is valid
     */
    private function verifyCartOwnership($quote, $quoteId, $result)
    {
        // Verify cart ownership: logged-in customer must own the cart
        if ($this->customerSession->isLoggedIn()) {
            $customerId = (int)$this->customerSession->getCustomerId();
            if ((int)$quote->getCustomerId() !== $customerId) {
                $this->logger->warning('SimplyIN PlaceMagentoOrder: Cart ownership mismatch', [
                    'session_customer_id' => $customerId,
                    'quote_customer_id' => $quote->getCustomerId()
                ]);
                return $result->setData([
                    'success' => false,
                    'message' => __('Unauthorized access to cart')
                ])->setHttpResponseCode(403);
            }
        } else {
            // Guest user: verify the session owns this cart
            $sessionQuoteId = $this->checkoutSession->getQuoteId();
            if ($sessionQuoteId && (int)$sessionQuoteId !== (int)$quoteId) {
                $this->logger->warning('SimplyIN PlaceMagentoOrder: Guest cart ownership mismatch', [
                    'session_quote_id' => $sessionQuoteId,
                    'requested_quote_id' => $quoteId
                ]);
                return $result->setData([
                    'success' => false,
                    'message' => __('Unauthorized access to cart')
                ])->setHttpResponseCode(403);
            }
        }

        return null;
    }
}
