<?php

namespace App\Services\Integrations;

use GuzzleHttp\Client;
use App\Models\ApiCredential;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class RevivnIntegrationService
{


    /**
     * Get the API credentials for the 'revivn' slug.
     *
     * @return \App\Models\ApiCredential|null The API credentials or null if not found.
     */
    protected function getApiCredentials()
    {
        return Cache::remember('revivn-credentials', 720, function () {
            return ApiCredential::where('slug', 'revivn')->first();
        });
    }

    /**
     * Get the base URL from the cached API credentials.
     *
     * @return string|null The base URL or null if API credentials are not available.
     */
    protected function getApiBaseUrl()
    {
        $credential = $this->getApiCredentials();
        return optional($credential)->url;
    }

    /**
     * Get the access token using the client credentials grant type.
     *
     * @return string|null The access token on success, or null on failure.
     */
    protected function getToken()
    {
        try {
            $cachedToken = Cache::get('revivn-access-token');

            if (!is_null($cachedToken)) {
                return $cachedToken;
            }

            $credential = $this->getApiCredentials();
            $baseUrl = optional($credential)->url;
            $clientId = optional($credential)->user_name;
            $clientSecret = optional($credential)->password;
            $url = $baseUrl . 'oauth/token';

            $response = Http::post($url, [
                'grant_type' => 'client_credentials',
                'client_id' => $clientId,
                'client_secret' => $clientSecret,
            ]);

            $responseData = $response->json();
            Cache::put('api-access-token', $responseData['access_token'], $responseData['expires_in'] ?? 60);

            return $responseData['access_token'];
        } catch (\Throwable $th) {

            return null;
        }
    }

    /**
     * Initializes the HTTP client.
     *
     * @return Client The initialized HTTP client.
     */
    protected function initializeHttpClient()
    {
        return Http::withOptions([
            'verify' => false,
        ])->withHeaders([
            'Accept' => 'application/json',
            'Authorization' => 'Bearer ' . $this->getToken(),
            'Content-Type' => 'application/json',
        ]);
    }



    /**
     * Checks the connection to the API.
     *
     * @throws Exception if there is an error connecting to the API.
     * @return bool true if the connection is successful, false otherwise.
     */
    public function checkApiConnection()
    {
        try {
            $response = Http::withToken($this->getToken())
                ->retry(2, 1000)
                ->get($this->getApiBaseUrl() . 'api/v1/assets?page[size]=1&page[number]=1')
                ->throw();

            return $response->successful();
        } catch (Exception $e) {
            Log::channel('single')->info("Revivn API Connection Error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * Retrieves a list of pickups from the API.
     *
     * @return The list of pickups.
     */
    public function getPickups()
    {
        $client = $this->initializeHttpClient();
        $response = $client->get($this->getApiBaseUrl() . "api/v1/pickups");
        return json_decode($response->getBody()->getContents());
    }


    /**
     * Retrieves the assets for a given pickup ID.
     *
     * @param int $pickupId The ID of the pickup.
     * @throws Exception If there is an error retrieving the assets.
     * @return mixed The assets data as an array.
     */
    public function getAssets($page = 1)
    {
        $client = $this->initializeHttpClient();
        $response = $client->get($this->getApiBaseUrl() . "api/v1/assets?page[size]=200&page[number]=" . $page);

        return json_decode($response->getBody()->getContents());
    }
}
