<?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 Simplyin\Payment\Service\CheckoutOwnershipGuard;
use Simplyin\Payment\Service\CreateOrderService;
use Psr\Log\LoggerInterface;

/**
 * Resolver: simplyinCreateOrder mutation
 *
 * Headless counterpart of the CreateOrder REST controller. Delegates SimplyIN
 * order creation (with payment processing) to the shared {@see CreateOrderService}
 * and flattens the result to the GraphQL output type (dynamic payload kept in
 * raw_json, following the module's raw_json convention).
 */
class CreateOrder extends AbstractResolver
{
    /**
     * @var CreateOrderService
     */
    private CreateOrderService $createOrderService;

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

    /**
     * @param CreateOrderService $createOrderService
     * @param CheckoutOwnershipGuard $ownershipGuard
     * @param LoggerInterface $logger
     */
    public function __construct(
        CreateOrderService $createOrderService,
        CheckoutOwnershipGuard $ownershipGuard,
        LoggerInterface $logger
    ) {
        parent::__construct($logger);
        $this->createOrderService = $createOrderService;
        $this->ownershipGuard = $ownershipGuard;
    }

    /**
     * @inheritdoc
     */
    public function resolve(Field $field, $context, ResolveInfo $info, ?array $value = null, ?array $args = null): array
    {
        $args = $args ?? [];
        $this->requireArg($args, 'order_data_json');

        $orderData = json_decode((string)$args['order_data_json'], true);
        // Must be a JSON object (map). Reject non-arrays and JSON lists such as
        // "[1,2]" (empty "[]"/"{}" both decode to [] and are allowed as "no data").
        if (!is_array($orderData) || (array_is_list($orderData) && $orderData !== [])) {
            throw new GraphQlInputException(__('"order_data_json" must be a valid JSON object.'));
        }

        // IDOR guard: an authenticated customer may only act on their
        // own order/cart. Identity comes from $context (GraphQL is stateless).
        $customerId = $this->customerIdFromContext($context);
        if (!$this->ownershipGuard->isOrderOwnedBy($customerId, $orderData['magentoOrderId'] ?? null)
            || !$this->ownershipGuard->isQuoteOwnedBy($customerId, $orderData['quoteId'] ?? null)) {
            throw new GraphQlAuthorizationException(__('Unauthorized access to checkout.'));
        }

        try {
            $result = $this->createOrderService->create([
                'orderData'     => $orderData,
                'authToken'     => $args['auth_token'] ?? '',
                'createAccount' => $args['create_account'] ?? false,
                'isNewUser'     => $args['is_new_user'] ?? false,
            ]);
        } catch (\Exception $e) {
            $this->logger->error('SimplyIN GraphQL CreateOrder: ' . $e->getMessage());
            return $this->errorOutput('An unexpected error occurred. Please try again.');
        }

        return $this->flattenOrderResult($result);
    }

    /**
     * Flatten a create-order result array to the GraphQL output shape.
     *
     * @param array $result
     * @return array
     */
    private function flattenOrderResult(array $result): array
    {
        $info = $result['paymentInfo'] ?? [];

        return [
            'success'                   => (bool)($result['success'] ?? false),
            'message'                   => isset($result['message']) ? (string)$result['message'] : null,
            'simplyin_order_id'         => $info['simplyin_order_id'] ?? null,
            'payment_id'                => $info['simplyin_payment_id'] ?? null,
            'provider_payment_id'       => $info['simplyin_provider_payment_id'] ?? null,
            'payment_status'            => $info['simplyin_payment_status'] ?? null,
            'redirect_url'              => $info['simplyin_redirect_url'] ?? null,
            'redirect_iframe_allowed'   => (bool)($info['simplyin_redirect_iframe_allowed'] ?? false),
            'magento_order_id'          => isset($result['magentoOrderId']) ? (string)$result['magentoOrderId'] : null,
            'payment_only'              => (bool)($result['paymentOnly'] ?? false),
            'requires_account'          => (bool)($result['requiresAccount'] ?? false),
            'skip_payment_verification' => (bool)($result['skipPaymentVerification'] ?? false),
            'auth_token'                => $result['authToken'] ?? null,
            // Only the provider payment object — never the order/billing PII the
            // flat fields deliberately omit.
            'raw_json'                  => isset($result['payment']) ? json_encode($result['payment']) : null,
        ];
    }
}
