<?php
namespace EasyChat\Library\Commerce;

use EasyChat\Library\Http\ExternalHttpClient;

 
final class MoySkladClient
{
    private const BASE_URL = 'https://api.moysklad.ru/api/remap/1.2/';
    private $http;
    private $token;

    public function __construct($registry, string $token, ?ExternalHttpClient $http = null)
    {
        $this->http = $http ?: new ExternalHttpClient($registry);
        $this->token = trim($token);
    }

    public function test(): array
    {
        $payload = $this->get('context/employee');
         
         
        $this->get('entity/counterparty', array('limit' => 1));
        $this->get('entity/customerorder', array('limit' => 1));
        return array(
            'success' => !empty($payload['id']) || !empty($payload['meta']['href']),
            'account' => $this->plain($payload['name'] ?? $payload['fullName'] ?? '', 120),
        );
    }

    public function counterparties(string $field, string $value): array
    {
        if (!in_array($field, array('email', 'phone'), true) || trim($value) === '') return array();
        $payload = $this->get('entity/counterparty', array('filter' => $field . '=' . trim($value), 'limit' => 3));
        return is_array($payload['rows'] ?? null) ? $payload['rows'] : array();
    }

    public function customerOrders(string $counterparty_href, int $limit): array
    {
        if (!$this->isApiHref($counterparty_href)) return array();
        $payload = $this->get('entity/customerorder', array(
            'filter' => 'agent=' . $counterparty_href,
            'order' => 'moment,desc',
            'limit' => max(1, min(10, $limit)),
            'expand' => 'state,positions,positions.assortment',
            'fields' => 'stock',
        ));
        return is_array($payload['rows'] ?? null) ? $payload['rows'] : array();
    }

     
    public function metadata(string $entity): array
    {
        if (!in_array($entity, array('customerorder', 'demand'), true)) return array();
        $payload = $this->get('entity/' . $entity . '/metadata/attributes');
         
         
         
        if (is_array($payload['rows'] ?? null)) return $payload['rows'];
        return is_array($payload['attributes'] ?? null) ? $payload['attributes'] : array();
    }

     
    public function demands(array $customer_order_hrefs, int $limit = 10): array
    {
        $result = array();
        foreach (array_slice($customer_order_hrefs, 0, 10) as $href) {
            if (!$this->isApiHref((string)$href, 'customerorder')) continue;
            $payload = $this->get('entity/demand', array(
                'filter' => 'customerOrder=' . $href,
                'order' => 'moment,desc',
                'limit' => max(1, min(10, $limit)),
                'expand' => 'customerOrder,carrier,state',
            ));
            foreach ((array)($payload['rows'] ?? array()) as $row) $result[] = $row;
        }
        return $result;
    }

    private function get(string $path, array $query = array()): array
    {
        if ($this->token === '') throw new \RuntimeException('moysklad_token_required');
        $url = self::BASE_URL . ltrim($path, '/');
        if ($query) $url .= '?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
        $result = $this->http->request('GET', $url, array(
            'headers' => array(
                'Authorization: Bearer ' . $this->token,
                'Accept: application/json',
                'Accept-Language: ru',
                'Accept-Encoding: gzip',
                'User-Agent: EasyChat-MoySklad/1.0',
            ),
            'connect_timeout' => 4,
            'timeout' => 12,
            'trust_profile' => 'moysklad',
            'allow_tls_fallback' => true,
            'curl_options' => defined('CURLOPT_ENCODING') ? array(CURLOPT_ENCODING => '') : array(),
        ));
        if (empty($result['transport_ok'])) throw new \RuntimeException('moysklad_transport_failed');
        $status = (int)($result['http_code'] ?? 0);
        if ($status === 401 || $status === 403) throw new \RuntimeException('moysklad_credentials_invalid');
        if ($status === 429) throw new \RuntimeException('moysklad_rate_limited');
        if ($status < 200 || $status >= 300) throw new \RuntimeException('moysklad_http_' . $status);
        $decoded = json_decode((string)($result['raw'] ?? ''), true);
        if (!is_array($decoded)) throw new \RuntimeException('moysklad_invalid_response');
        return $decoded;
    }

    private function isApiHref(string $href, string $entity = 'counterparty'): bool
    {
        return strpos($href, self::BASE_URL . 'entity/' . $entity . '/') === 0
            && preg_match('~/[0-9a-f-]{30,40}$~i', $href) === 1;
    }

    private function plain($value, int $limit): string
    {
        return mb_substr(trim(preg_replace('/\s+/u', ' ', strip_tags((string)$value))), 0, $limit, 'UTF-8');
    }
}
