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

namespace Simplyin\Payment\Service\Api;

use Magento\Store\Model\ScopeInterface;

/**
 * Address search and parcel locker SimplyIN API operations.
 */
class AddressParcelApiClient
{
    /**
     * @var ApiTransport
     */
    private ApiTransport $transport;

    /**
     * Constructor
     *
     * @param ApiTransport $transport
     */
    public function __construct(ApiTransport $transport)
    {
        $this->transport = $transport;
    }

    /**
     * Get closest parcel lockers based on coordinates
     *
     * Uses the parcelLockers/getClosest endpoint
     *
     * @param float $lat Latitude
     * @param float $lng Longitude
     * @param array $providers Accepted parcel locker providers
     * @param int $limit Number of items to find
     * @param int $radius Search radius in meters
     * @param string $authToken Auth token
     * @return array
     */
    public function getClosestParcelLockers($lat, $lng, $providers = [], $limit = 20, $radius = 5000, $authToken = '')
    {
        $url = $this->transport->getApiBaseUrl() . '/parcelLockers/getClosest';

        if ($authToken) {
            $url .= '?api_token=' . urlencode($authToken);
        }

        $headers = [
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ];

        $this->transport->getCurl()->setHeaders($headers);

        $body = [
            'numberOfItemsToFind' => $limit,
            'searchRadiusInMeters' => $radius,
            'coordinates' => [
                'lat' => (float)$lat,
                'lng' => (float)$lng
            ],
            'acceptedParcelLockerProviders' => $providers
        ];

        try {
            $this->transport->getCurl()->post($url, json_encode($body));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                $decoded = json_decode($response, true);
                return [
                    'success' => true,
                    'data' => $decoded['data'] ?? $decoded
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to get closest parcel lockers'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Get user parcel lockers info from user data
     *
     * Fetches parcel lockers saved in user's SimplyIN profile
     *
     * @param string $authToken
     * @return array
     */
    public function getUserParcelLockersInfo($authToken)
    {
        $url = $this->transport->getApiBaseUrl() . '/userDataCommerce/users/parcelLockersInfo';

        if ($authToken) {
            $url .= '?api_token=' . urlencode($authToken);
        }

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $this->transport->getCurl()->get($url);
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to get user parcel lockers info'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    /**
     * Get shipping method mapping configuration
     *
     * @return array
     */
    public function getShippingMethodMapping()
    {
        $mapping = [];
        $basePath = 'payment/shipping_methods/';

        $methods = [
            'dpd_pickup' => 'dpd',
            'dhl_box_pop' => 'dhl',
            'fedex_pickup' => 'fedex',
            'inpost_paczkomat' => 'inpost',
            'orlen_punkty' => 'orlen',
            'ups_pickup' => 'ups'
        ];

        foreach ($methods as $configKey => $provider) {
            $value = $this->transport->getScopeConfig()->getValue(
                $basePath . $configKey,
                ScopeInterface::SCOPE_STORE
            );
            if ($value) {
                $mapping[$provider] = $value;
            }
        }

        $defaultCourier = $this->transport->getScopeConfig()->getValue(
            $basePath . 'default_courier',
            ScopeInterface::SCOPE_STORE
        );

        if ($defaultCourier) {
            $mapping['default_courier'] = $defaultCourier;
        }

        return $mapping;
    }

    /**
     * Get available parcel locker providers based on admin configuration
     *
     * @return array
     */
    public function getAvailableParcelLockerProviders()
    {
        $mapping = $this->getShippingMethodMapping();
        $providers = [];

        // Map config keys to API provider names
        $providerMap = [
            'dpd' => 'dpd',
            'dhl' => 'dhl',
            'fedex' => 'fedex',
            'inpost' => 'inpost',
            'orlen' => 'orlen',
            'ups' => 'ups'
        ];

        foreach ($providerMap as $configKey => $apiProvider) {
            if (isset($mapping[$configKey]) && !empty($mapping[$configKey])) {
                $providers[] = $apiProvider;
            }
        }

        // If no providers configured, return all available
        if (empty($providers)) {
            $providers = array_values($providerMap);
        }

        return $providers;
    }

    /**
     * Search address
     *
     * @param string $query
     * @param string $authToken
     * @return array
     */
    public function searchAddress($query, $authToken)
    {
        $url = $this->transport->getApiBaseUrl() . '/addresses/find';

        // Add api_token as query parameter (matching Swagger API format)
        if ($authToken) {
            $url .= '?api_token=' . urlencode($authToken);
        }

        $this->transport->getCurl()->setHeaders([
            'Content-Type' => 'application/json',
            'accept' => 'application/json',
            'Origin' => $this->transport->getOrigin(),
            'X-Auth-Merchant-Api-Key' => $this->transport->getApiKey()
        ]);

        try {
            $this->transport->getCurl()->post($url, json_encode(['searchAddressBy' => $query]));
            $response = $this->transport->getCurl()->getBody();
            $statusCode = $this->transport->getCurl()->getStatus();

            if ($statusCode >= 200 && $statusCode < 300) {
                return [
                    'success' => true,
                    'data' => json_decode($response, true)
                ];
            } else {
                $decoded = json_decode($response, true);
                return [
                    'success' => false,
                    'error' => $decoded['message'] ?? __('Failed to search addresses'),
                    'response' => $response
                ];
            }
        } catch (\Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
}
