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

namespace Simplyin\Payment\Model\Resolver;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Checkout\Model\Session as CheckoutSession;
use Simplyin\Payment\Api\PickupPointProcessorInterface;
use Simplyin\Payment\Service\CheckoutOwnershipGuard;
use Psr\Log\LoggerInterface;

/**
 * Resolver: simplyinSetPickupPoint mutation
 */
class SetPickupPoint extends AbstractResolver
{
    /**
     * @var CartRepositoryInterface
     */
    private CartRepositoryInterface $cartRepository;

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

    /**
     * @var PickupPointProcessorInterface
     */
    private PickupPointProcessorInterface $pickupPointProcessor;

    /**
     * @var CheckoutOwnershipGuard
     */
    private CheckoutOwnershipGuard $ownershipGuard;

    /**
     * @param CartRepositoryInterface $cartRepository
     * @param CheckoutSession $checkoutSession
     * @param PickupPointProcessorInterface $pickupPointProcessor
     * @param CheckoutOwnershipGuard $ownershipGuard
     * @param LoggerInterface $logger
     */
    public function __construct(
        CartRepositoryInterface $cartRepository,
        CheckoutSession $checkoutSession,
        PickupPointProcessorInterface $pickupPointProcessor,
        CheckoutOwnershipGuard $ownershipGuard,
        LoggerInterface $logger
    ) {
        parent::__construct($logger);
        $this->cartRepository       = $cartRepository;
        $this->checkoutSession      = $checkoutSession;
        $this->pickupPointProcessor = $pickupPointProcessor;
        $this->ownershipGuard       = $ownershipGuard;
    }

    /**
     * @inheritdoc
     */
    public function resolve(Field $field, $context, ResolveInfo $info, ?array $value = null, ?array $args = null): array
    {
        $quoteId      = $args['quote_id'] ?? '';
        $lockerId     = trim($args['locker_id'] ?? '');
        $providerName = trim($args['provider_name'] ?? '');

        if (empty($quoteId) || empty($lockerId) || empty($providerName)) {
            throw new GraphQlInputException(__('quote_id, locker_id and provider_name are required.'));
        }

        // IDOR guard: an authenticated customer may only set a pickup
        // point on their own cart. Identity comes from $context (GraphQL is stateless).
        if (!$this->ownershipGuard->isQuoteOwnedBy($this->customerIdFromContext($context), $quoteId)) {
            throw new GraphQlAuthorizationException(__('Unauthorized access to cart.'));
        }

        try {
            // Resolve quote
            $quote = $this->resolveQuote($quoteId);

            if (!$quote || !$quote->getId()) {
                return $this->errorOutput('Quote not found');
            }

            // Build pickup point data
            $lockerData = $args['locker_data'] ?? [];
            $pickupPointData = array_merge($lockerData, [
                'lockerId'     => $lockerId,
                'providerName' => $providerName,
            ]);

            $result = $this->pickupPointProcessor->process($quote, $pickupPointData);
            $this->cartRepository->save($quote);

            return [
                'success' => true,
                'message' => $result
                    ? 'Pickup point set successfully'
                    : 'Pickup point data received but module integration was skipped',
            ];
        } catch (\Exception $e) {
            $this->logger->error('SimplyIN GraphQL SetPickupPoint: ' . $e->getMessage());
            return $this->errorOutput('An unexpected error occurred. Please try again.');
        }
    }

    /**
     * Resolve the quote from the checkout session or cart repository
     *
     * @param mixed $quoteId The quote ID argument
     * @return \Magento\Quote\Api\Data\CartInterface|null The resolved quote or null
     */
    private function resolveQuote($quoteId)
    {
        $quote = null;
        try {
            $sessionQuote = $this->checkoutSession->getQuote();
            if ($sessionQuote && $sessionQuote->getId() && (int)$sessionQuote->getId() === (int)$quoteId) {
                $quote = $sessionQuote;
            }
        } catch (\Exception $e) { // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock.DetectedCatch -- intentional: checkout session may be unavailable, fall through to cart-repository lookup below
            // ignore session errors
        }

        if (!$quote) {
            try {
                $quote = $this->cartRepository->get($quoteId);
            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
                $quote = $this->checkoutSession->getQuote();
            }
        }

        return $quote;
    }
}
