<?php

/**
 * EventBookings API Service Class
 *
 * Handles all API communication with the EventBookings service
 *
 * @since 1.1
 */
class Eventbookings_Api_Service
{

    /**
     * Handle API requests to EventBookings service
     *
     * @since 1.1
     * @param string $method HTTP method (GET, POST, PUT, DELETE)
     * @param string $endpoint API endpoint URL
     * @param array $body Request body data
     * @param bool $retry Whether to retry on authentication failure
     * @return array API response or error array
     */
    public static function eventbookings_api_request_handler($method, $endpoint, $body = [], $retry = true)
    {
        $access_token = self::eventbookings_get_access_token();

        if (!$access_token) {
            return ['error' => 'Invalid or missing access token'];
        }

        $args = [
            'headers' => [
                'Authorization' => 'Bearer ' . $access_token,
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
            ],
            'timeout' => 20,
        ];

        if (!empty($body) && in_array(strtoupper($method), ['POST', 'PUT', 'PATCH'])) {
            $args['body'] = json_encode($body);
        }

        switch (strtoupper($method)) {
            case 'GET':
                $response = wp_remote_get($endpoint, $args);
                break;
            case 'POST':
                $response = wp_remote_post($endpoint, $args);
                break;
            case 'PUT':
            case 'PATCH':
            case 'DELETE':
                $args['method'] = strtoupper($method);
                $response = wp_remote_request($endpoint, $args);
                break;
            default:
                return ['error' => 'Unsupported HTTP method'];
        }

        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            eventbookings_log('error', 'API request failed: ' . $error_message, ['endpoint' => $endpoint, 'method' => $method]);
            return ['error' => $error_message];
        }

        $http_code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        if (($http_code == 401 || (isset($body['error']) && stripos($body['error'], 'access denied') !== false)) && $retry) {
            eventbookings_log('info', 'Token expired, attempting to refresh', ['http_code' => $http_code]);
            $new_token = self::eventbookings_fetch_new_token();
            if ($new_token) {
                eventbookings_log('info', 'Token refreshed successfully');
                return self::eventbookings_api_request_handler($method, $endpoint, $body, false);
            } else {
                eventbookings_log('error', 'Failed to refresh token');
            }
        }

        return $body ?? ['error' => "Invalid API response (HTTP Code: $http_code)"];
    }

    /**
     * Get the stored access token from database
     *
     * @since 1.1
     * @return string The access token or empty string if not found
     */
    public static function eventbookings_get_access_token()
    {
        global $wpdb;
        $table_name = $wpdb->prefix . 'eb_plugin_users';
        $result = $wpdb->get_row($wpdb->prepare("SELECT access_token FROM %i LIMIT %d", $table_name, 1));
        return $result ? $result->access_token : '';
    }

    /**
     * Fetch a new access token from the EventBookings identity service
     *
     * @since 1.1
     * @return string|null The new access token or null on failure
     */
    public static function eventbookings_fetch_new_token()
    {
        global $wpdb;
        $table_name = $wpdb->prefix . 'eb_plugin_users';
        $user = $wpdb->get_row($wpdb->prepare("SELECT client_id, client_secret FROM %i LIMIT %d", $table_name, 1));

        if (!$user) return null;

        $client_id = $user->client_id;
        $client_secret = $user->client_secret;

        // Call API to refresh token
        $response = wp_remote_post(EVENTBOOKINGS_IDENTITY_URL . '/connect/token', [
            'body' => [
                'client_id' => $client_id,
                'client_secret' => $client_secret,
                'grant_type' => 'client_credentials',
            ],
        ]);

        if (is_wp_error($response)) {
            return null;
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);
        if (!isset($body['access_token'])) {
            return null;
        }

        // Update the new token in DB
        $wpdb->update($table_name, ['access_token' => $body['access_token']], ['client_id' => $client_id]);

        return $body['access_token'];
    }
}
