<?php

namespace PortalPeople\magento\services;

use Psr\Log\LoggerInterface;
use yii\httpclient\Client;
use yii\httpclient\Exception as HttpClientException;

class MagentoClient
{
    private Client $httpClient;
    private string $baseUrl;
    private string $token;
    private ?LoggerInterface $logger;

    public function __construct(string $baseUrl, string $accessToken, LoggerInterface $logger = null)
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->token = $accessToken;
        $this->httpClient = new Client([
            'baseUrl' => $this->baseUrl . '/',
            'requestConfig' => [
                'format' => Client::FORMAT_JSON,
                'options' => [
                    CURLOPT_TIMEOUT => 30,
                    CURLOPT_CONNECTTIMEOUT => 10,
                ],
            ],
            'responseConfig' => [
                'format' => Client::FORMAT_JSON,
            ],
        ]);
        $this->logger = $logger;
    }

    protected function headers(): array
    {
        return [
            'Authorization' => 'Bearer ' . $this->token,
            'Accept' => 'application/json',
            'Content-Type' => 'application/json; charset=UTF-8',
        ];
    }

    /**
     * Fetch orders from Magento. Example: GET /rest/V1/orders?searchCriteria[pageSize]=50
     * @param array $query
     * @return array
     */
    public function getOrders(array $query = []): array
    {
        return $this->request('GET', 'rest/V1/orders', $query);
    }

    public function getOrder(int $id): array
    {
        return $this->request('GET', 'rest/V1/orders/' . rawurlencode((string) $id));
    }

    public function updateOrderNgaugeFields(int $id, string $ngaugeOrderId, string $ngaugeOrderNo, string $ngaugeOrderLink): array
    {
        return $this->request('POST', 'rest/V1/orders', [
            'entity' => [
                'entity_id' => $id,
                'extension_attributes' => [
                    'ngauge_order_id' => $ngaugeOrderId,
                    'ngauge_order_no' => $ngaugeOrderNo,
                    'ngauge_order_link' => $ngaugeOrderLink,
                ],
            ],
        ]);
    }

    public function addOrderComment(int $magentoOrderId, string $comment, string $status = 'processing'): array
    {
        return $this->request('POST', 'rest/V1/orders/' . rawurlencode((string) $magentoOrderId) . '/comments', [
            'statusHistory' => [
                'comment' => $comment,
                'is_customer_notified' => 0,
                'is_visible_on_front' => 0,
            ],
        ]);
    }

    public function request(string $method, string $uri, array $query = []): array
    {
        if ($this->logger !== null) {
            $this->logger->info(sprintf('Magento API %s %s', $method, $uri), $query);
        }

        try {
            $request = $this->httpClient->createRequest()
                ->setMethod($method)
                ->addHeaders($this->headers())
                ->setUrl($uri);

            if ($query !== []) {
                if (strtoupper($method) === 'GET') {
                    $request->setUrl($uri . '?' . http_build_query($query));
                } else {
                    $request->setData($query);
                }
            }

            $response = $request->send();
            $statusCode = (int) $response->statusCode;

            if ($statusCode < 200 || $statusCode >= 300) {
                throw new \RuntimeException('Magento API request failed with status ' . $statusCode);
            }

            $data = $response->getData();

            return is_array($data) ? $data : [];
        } catch (HttpClientException $e) {
            if ($this->logger !== null) {
                $this->logger->error('Magento API request failed: ' . $e->getMessage());
            }

            throw new \RuntimeException('Magento API request failed: ' . $e->getMessage(), 0, $e);
        }
    }
}
