<?php
/**
 * PA-API HTTP request execution and AWS Signature V4
 *
 * Handles signing, HTTP execution via wp_remote_post(), and error handling.
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Helper function for AWS signature
 */
function psfa_sign($key, $msg) { 
    return hash_hmac('sha256', $msg, $key, true); 
}

// @codeCoverageIgnoreStart
/**
 * Execute a PA-API SearchItems request using the given configuration and payload.
 *
 * This wraps signing, HTTP execution via wp_remote_post(), and basic error handling.
 *
 * @param array $config  Configuration from psfa_get_api_config().
 * @param array $payload Already-built SearchItems payload.
 * @return array Associative array representing the decoded API response or an error structure.
 */
function psfa_execute_paapi_request(array $config, array $payload) {
    $access_key    = $config['access_key'];
    $secret_key    = $config['secret_key'];
    $endpoint      = $config['endpoint'];
    $uri           = $config['uri'];
    $region        = $config['region'];
    $service       = $config['service'];
    $content_type  = $config['content_type'];
    $amz_target    = $config['amz_target'];

    // Remove parameters not supported by PA-API v5 (only Creators API supports these)
    unset($payload['MinPrice'], $payload['MaxPrice']);

    $request_payload = json_encode($payload);

    $headers = array(
        "Content-Encoding:amz-1.0",
        "Content-Type:$content_type",
        "Host:$endpoint",
        "X-Amz-Target:$amz_target",
    );

    // AWS SIGNATURE V4
    $amz_date            = gmdate('Ymd\THis\Z');
    $date_stamp          = gmdate('Ymd');
    $canonical_uri       = $uri;
    $canonical_querystring = '';

    $canonical_headers = "content-encoding:amz-1.0\ncontent-type:$content_type\nhost:$endpoint\nx-amz-date:$amz_date\nx-amz-target:$amz_target\n";
    $signed_headers    = "content-encoding;content-type;host;x-amz-date;x-amz-target";
    $payload_hash      = hash('sha256', $request_payload);

    $canonical_request = "POST\n$canonical_uri\n$canonical_querystring\n$canonical_headers\n$signed_headers\n$payload_hash";

    $algorithm       = 'AWS4-HMAC-SHA256';
    $credential_scope = "$date_stamp/$region/$service/aws4_request";
    $string_to_sign   = "$algorithm\n$amz_date\n$credential_scope\n" . hash('sha256', $canonical_request);

    // Generate signing key
    $kSecret  = 'AWS4' . $secret_key;
    $kDate    = psfa_sign($kSecret, $date_stamp);
    $kRegion  = psfa_sign($kDate, $region);
    $kService = psfa_sign($kRegion, $service);
    $kSigning = psfa_sign($kService, 'aws4_request');
    $signature = hash_hmac('sha256', $string_to_sign, $kSigning);

    $authorization_header = "$algorithm Credential=$access_key/$credential_scope, SignedHeaders=$signed_headers, Signature=$signature";

    $headers[] = "X-Amz-Date:$amz_date";
    $headers[] = "Authorization:$authorization_header";

    // Convert headers array to WordPress HTTP API format
    $wp_headers = array();
    foreach ($headers as $header) {
        $parts = explode(':', $header, 2);
        if (count($parts) === 2) {
            $wp_headers[trim($parts[0])] = trim($parts[1]);
        }
    }

    // WordPress HTTP API REQUEST
    $request_args = array(
        'method'    => 'POST',
        'headers'   => $wp_headers,
        'body'      => $request_payload,
        'timeout'   => 8,
        'sslverify' => true,
    );

    $response = wp_remote_post("https://{$endpoint}{$uri}", $request_args);

    // Check for WordPress HTTP API errors
    if (is_wp_error($response)) {
        return array('error' => 'HTTP Error: ' . $response->get_error_message());
    }

    $http_code     = wp_remote_retrieve_response_code($response);
    $response_body = wp_remote_retrieve_body($response);

    // Check HTTP status
    if ($http_code !== 200) {
        $error_details = '';
        if (!empty($response_body)) {
            $error_data = json_decode($response_body, true);
            if (isset($error_data['Errors'])) {
                $error_details = ' - ' . json_encode($error_data['Errors']);
            } elseif (isset($error_data['__type'])) {
                $error_details = ' - ' . $error_data['__type'] . ': ' . ($error_data['message'] ?? '');
            } else {
                $error_details = ' - Response: ' . substr($response_body, 0, 200);
            }
        }
        return array(
            'error'    => 'HTTP Error: ' . $http_code . $error_details,
            'response' => $response_body,
            'http_code'=> $http_code,
        );
    }

    $decoded = json_decode($response_body, true);

    // Check for API errors in response
    if (isset($decoded['Errors'])) {
        $errors = $decoded['Errors'];
        if (is_array($errors) && count($errors) > 0) {
            $first_error = $errors[0];
            if (isset($first_error['Code']) && $first_error['Code'] === 'NoResults') {
                // Treat "NoResults" as an empty result set for nicer UX.
                return array(
                    'SearchResult' => array(
                        'Items'            => array(),
                        'TotalResultCount' => 0,
                    ),
                );
            }
        }
        return array('error' => 'API Error', 'details' => $decoded['Errors'], 'full_response' => $decoded);
    }

    // Valid responses have either SearchResult (SearchItems) or ItemsResult (GetItems)
    if (!isset($decoded['SearchResult']) && !isset($decoded['ItemsResult'])) {
        return array('error' => 'Invalid API response', 'full_response' => $decoded);
    }

    return $decoded;
}
// @codeCoverageIgnoreEnd

