<?php

namespace App\Services;

use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class KedebahService
{

    protected function get(string $path, array $queryParams = []): Response
    {
        $token = $this->getApiToken();
        $path = $this->apiUrl() . $path;

        $apiCall = Http::withToken($token)->acceptJson()->asJson()
            ->timeout(0)
            // ->withQueryParameters($queryParams)
            ->get($path, $queryParams);

        // Log API call and response
        $requestId = $this->logApiCall(
            method: 'GET',
            path: $path,
            token: $token,
            query: $queryParams,
        );
        $this->logApiResponse(requestUuid: $requestId, response: $apiCall);

        return $apiCall;
    }


    protected function post(string $path, array $data = [], array $queryParams = []): Response
    {

        $token = $this->getApiToken();
        $path = $this->apiUrl() . $path;

        $apiCall = Http::withToken($token)->acceptJson()->asJson()
            ->timeout(0)
            ->withQueryParameters($queryParams)
            ->post($path, $data);


        // Log API call and response
        $requestId = $this->logApiCall(
            method: 'POST',
            path: $path,
            token: $token,
            data: $data,
            query: $queryParams,
        );
        $this->logApiResponse(requestUuid: $requestId, response: $apiCall);

        return $apiCall;
    }


    protected function put(string $path, array $data = [], array $queryParams = []): Response
    {

        $token = $this->getApiToken();
        $path = $this->apiUrl() . $path;

        $apiCall = Http::withToken($token)->acceptJson()->asJson()
            ->timeout(0)
            ->withQueryParameters($queryParams)
            ->put($path, $data);


        // Log API call and response
        $requestId = $this->logApiCall(
            method: 'PUT',
            path: $path,
            token: $token,
            data: $data,
            query: $queryParams,
        );
        $this->logApiResponse(requestUuid: $requestId, response: $apiCall);

        return $apiCall;
    }

    protected function patch(string $path, array $data = [], array $queryParams = []): Response
    {
        // dd($path);

        $token = $this->getApiToken();
        $path = $this->apiUrl() . $path;

        $apiCall = Http::withToken($token)->acceptJson()->asJson()
            ->timeout(0)
            ->withQueryParameters($queryParams)
            ->patch($path, $data);
        // dd($path);
        // Log API call and response
        $requestId = $this->logApiCall(
            method: 'PATCH',
            path: $path,
            token: $token,
            data: $data,
            query: $queryParams,
        );
        $this->logApiResponse(requestUuid: $requestId, response: $apiCall);

        return $apiCall;
    }
    protected function delete(string $path, array $data = [], array $queryParams = []): Response
    {

        $token = $this->getApiToken();
        $path = $this->apiUrl() . $path;

        $apiCall = Http::withToken($token)->acceptJson()->asJson()
            ->timeout(0)
            ->withQueryParameters($queryParams)
            ->delete($path, $data);

        // Log API call and response
        $requestId = $this->logApiCall(
            method: 'DELETE',
            path: $path,
            token: $token,
            data: $data,
            query: $queryParams,
        );
        $this->logApiResponse(requestUuid: $requestId, response: $apiCall);

        return $apiCall;
    }


    protected function parseResponse(Response $response): object|string|null
    {
        // Handle Client Errors
        if ($response->clientError()) {
            // Validation error
            if ($response->unprocessableEntity()) {
                return $response->object()->message;
            }

            if ($response->unauthorized()) {
                SessionService::storeApiTokenExpiry(tokenHasExpired: true);
                return 'Session expired, please login';
            } else {
                SessionService::storeApiTokenExpiry(tokenHasExpired: false);
            }
        }

        // Handle Server Errors
        if ($response->serverError()) {
            return 'Server error';
        }

        if ($response->successful()) {
            if ($response->accepted() && $response->object()->message) {
                return $response->object()->message;
            }
            // NO CONTENT
            if ($response->noContent()) {
                return (object) [];
            }

            // dd(json_decode(json_encode($response->json())));

            return $response->object()->data === null
                ? $response->object()
                : $response->object()->data;
        }
        return null;
    }

    protected function apiUrl(): string|null
    {
        return null;
    }

    protected function getApiToken(): string|null
    {
        $token = Cookie::get('auth_token');
        return $token;
        // return SessionService::getApiToken() ?? '';
    }

    protected function logApiCall(string $method, string $path, string $token, array $data = [], array $query = []): string
    {
        $requestUuid = Str::orderedUuid()->toString();

        Log::channel('kedebah_api')->info('Calling KEDEBAH API', [
            'request_id' => $requestUuid,
            'token' => $token,
            'method' => $method,
            'path' => $path,
            'query' => $query,
            'data' => $data,
        ]);

        return $requestUuid;
    }
    protected function logApiResponse(string $requestUuid, Response $response): void
    {
        Log::channel('kedebah_api')->info('Receiving KEDEBAH API response', [
            'request_id' => $requestUuid,
            'status_code' => $response->status(),
            'response' => $response->json(),
        ]);
    }

}
