<?php

namespace App\Services;

use CodeIgniter\HTTP\CURLRequest;
use Config\Api as ApiConfig;

class ApiClient
{
    protected CURLRequest $http;
    protected ApiConfig $config;

    public function __construct(CURLRequest $http, ApiConfig $config)
    {
        $this->http = $http;
        $this->config = $config;
    }

    public function get(string $uri, array $query = [], array $headers = []): array
    {
        return $this->request('get', $uri, [
            'headers' => $this->mergeHeaders($headers),
            'query'   => $query,
        ]);
    }

    public function post(string $uri, array $data = [], array $headers = []): array
    {
        return $this->request('post', $uri, [
            'headers' => $this->mergeHeaders($headers, ['Content-Type' => 'application/json']),
            'json'    => $data,
        ]);
    }

    public function put(string $uri, array $data = [], array $headers = []): array
    {
        return $this->request('put', $uri, [
            'headers' => $this->mergeHeaders($headers, ['Content-Type' => 'application/json']),
            'json'    => $data,
        ]);
    }

    public function delete(string $uri, array $data = [], array $headers = []): array
    {
        return $this->request('delete', $uri, [
            'headers' => $this->mergeHeaders($headers, ['Content-Type' => 'application/json']),
            'json'    => $data,
        ]);
    }

    /**
     * Low-level access for uncommon HTTP methods or options
     */
    public function request(string $method, string $uri, array $options = []): array
    {
        $url = $this->fullUrl($uri);
        $options['timeout'] = $options['timeout'] ?? $this->config->timeout;

        $response = $this->http->request(strtoupper($method), $url, $options);

        $status = $response->getStatusCode();
        $body   = (string) $response->getBody();

        $decoded = null;
        if ($this->isJson($body)) {
            $decoded = json_decode($body, true);
        }

        return [
            'ok'        => $status >= 200 && $status < 300,
            'status'    => $status,
            'headers'   => $response->getHeaderLine('Content-Type'),
            'data'      => $decoded,
            'raw'       => $decoded === null ? $body : null,
        ];
    }

    protected function fullUrl(string $uri): string
    {
        if (preg_match('#^https?://#i', $uri)) {
            return $uri;
        }

        $base = rtrim($this->config->baseURL ?? '', '/');
        if ($base === '') {
            return '/' . ltrim($uri, '/');
        }
        return $base . '/' . ltrim($uri, '/');
    }

    protected function mergeHeaders(array $override = [], array $extra = []): array
    {
        $base = $this->config->defaultHeaders ?? [];
        return array_filter(array_merge($base, $extra, $override), static function ($v) {
            return $v !== null && $v !== '';
        });
    }

    protected function isJson(string $string): bool
    {
        json_decode($string);
        return json_last_error() === JSON_ERROR_NONE;
    }
}

?>

