<?php

namespace App\Services;

use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Mtc\AutoTraderStock\Services\AutoTraderApi as AutoTraderApiParent;

class AutoTraderApi extends AutoTraderApiParent
{
    /**
     * @var array
     */
    protected $config;

    public function __construct(array $config)
    {
        $this->config = $config;
    }

    /**
     * Call get request on API
     *
     * @param string $path
     * @return array|mixed
     */
    public function get(string $path, $key_to_fetch = null)
    {
        return Http::withHeaders($this->getHeaders())
            ->get($this->endpoint($path))
            ->onError(fn ($error) => Log::error('AutoTrader API error', [ $error ]))
            ->json($key_to_fetch);
    }

    /**
     * Call POST request on API
     *
     * @param string $path
     * @param array $body
     * @param array $options ['query' => [...]]
     * @param string|null $key_to_fetch
     * @return array|mixed
     */
    public function post(string $path, array $body = [], array $options = [], string|null $key_to_fetch = null)
    {
        $request = Http::withHeaders($this->getHeaders());

        if (isset($options['query'])) {
            $request->withQueryParameters($options['query']);
        }

        return $request
            ->post($this->endpoint($path), $body)
            ->onError(fn ($error) => Log::error('AutoTrader API error', ['body' => $body, 'error' => $error->json()]))
            ->json($key_to_fetch);
    }

    /**
     * Fetch access token for API
     *
     * @return string|null
     */
    public function accessToken(): ?string
    {
        return Cache::remember($this->cacheName('-access-token'), Carbon::now()->addMinutes(15), function () {
            $payload = [
                'key' => $this->config['api_key'],
                'secret' => $this->config['api_secret']
            ];

            return Http::post($this->endpoint('authenticate'), $payload)
                ->onError(fn ($error) => Log::error('AutoTrader API token error', [ $error ]))
                ->json('access_token');
        });
    }

    /**
     * Build endpoint for path on API
     *
     * @param string $path
     * @return string
     */
    public function endpoint(string $path)
    {
        if ($this->config['use_live_api']) {
            return 'https://api.autotrader.co.uk/' . $path;
        }
        return 'https://api-sandbox.autotrader.co.uk/' . $path;
    }

    /**
     * Get API request headers
     *
     * @return \string[][]
     */
    protected function getHeaders(): array
    {
        return [
            'Authorization' => 'Bearer ' . $this->accessToken()
        ];
    }

    protected function cacheName(string $key): string
    {
        return 'auto-trader-api' . $key;
    }
}
