<?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 Simplyin\Payment\Helper\ApiClient;
use Psr\Log\LoggerInterface;

/**
 * Add parcel locker controller
 *
 * Handles adding parcel lockers to user's SimplyIN account
 */
class AddParcelLocker implements HttpPostActionInterface, CsrfAwareActionInterface
{
    use CsrfAwareApiTrait;

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

    /**
     * @var ApiClient
     */
    private $apiClient;

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

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

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

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

            $validationError = $this->validateRequestData($authToken, $parcelLocker);
            if ($validationError !== null) {
                return $result->setData($validationError);
            }

            // Get current user data
            $userDataResponse = $this->apiClient->getUserData($authToken);
            if (!$userDataResponse['success']) {
                return $result->setData([
                    'success' => false,
                    'message' => __('Failed to get user data')
                ]);
            }

            // Handle nested data structure: API returns { data: { parcelLockers: [...] } }
            $userData = $userDataResponse['data'];
            if (isset($userData['data'])) {
                $userData = $userData['data'];
            }

            $userData = $this->upsertParcelLocker($userData, $parcelLocker);
            if ($userData === null) {
                return $result->setData([
                    'success' => false,
                    'message' => __('This parcel locker is already in your list')
                ]);
            }

            // Update user data
            $updateResponse = $this->apiClient->updateUserData(['userData' => $userData], $authToken);
            
            if ($updateResponse['success']) {
                return $result->setData([
                    'success' => true,
                    'message' => __('Parcel locker added successfully')
                ]);
            } else {
                return $result->setData([
                    'success' => false,
                    'message' => $updateResponse['error'] ?? __('Failed to add parcel locker')
                ]);
            }
        } catch (\Exception $e) {
            $this->logger->error('SimplyIN AddParcelLocker: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
            return $result->setData([
                'success' => false,
                'message' => __('An unexpected error occurred. Please try again.')
            ]);
        }
    }

    /**
     * Validate incoming request data
     *
     * @param string $authToken
     * @param array $parcelLocker
     * @return array|null Error response payload, or null when valid
     */
    private function validateRequestData($authToken, $parcelLocker): ?array
    {
        if (empty($authToken)) {
            return [
                'success' => false,
                'message' => __('Auth token is required')
            ];
        }

        if (empty($parcelLocker)) {
            return [
                'success' => false,
                'message' => __('Parcel locker data is required')
            ];
        }

        return null;
    }

    /**
     * Append parcel locker to user data, or return null if it already exists
     *
     * @param array $userData
     * @param array $parcelLocker
     * @return array|null Updated user data, or null when the locker already exists
     */
    private function upsertParcelLocker(array $userData, array $parcelLocker): ?array
    {
        // Initialize parcelLockers array if not exists
        if (!isset($userData['parcelLockers'])) {
            $userData['parcelLockers'] = [];
        }

        // Remove _id field if present - API will generate it
        // This matches PrestaShop plugin behavior
        if (isset($parcelLocker['_id'])) {
            unset($parcelLocker['_id']);
        }

        // Check if locker already exists (by lockerId)
        $lockerExists = false;
        foreach ($userData['parcelLockers'] as $existingLocker) {
            if (isset($existingLocker['lockerId']) &&
                isset($parcelLocker['lockerId']) &&
                $existingLocker['lockerId'] == $parcelLocker['lockerId']) {
                $lockerExists = true;
                break;
            }
        }

        if ($lockerExists) {
            return null;
        }

        // Add the new parcel locker
        $userData['parcelLockers'][] = $parcelLocker;

        return $userData;
    }
}
