<?php

declare(strict_types=1);

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

abstract class KLCNN_API_Base
{
  protected $base_url = 'https://sellerapi.kaufland.com/v2';
  protected $client_key;
  protected $secret_key;
  protected $storefront = 'de'; // For general API calls
  protected $locale = 'de-DE'; // For product data API calls

  public function __construct(string $client_key, string $secret_key, string $storefront = 'de', string $locale = 'de-DE')
  {
    $this->client_key = $client_key;
    $this->secret_key = $secret_key;
    $this->storefront = $storefront;
    $this->locale = $locale;
  }

  /**
   * Make an API request to Kaufland
   */
  protected function request(string $method, string $endpoint, array $body = []): array
  {
    try {
      // Validate and clean credentials before making request
      $this->client_key = trim($this->client_key);
      $this->secret_key = trim($this->secret_key);

      if (empty($this->client_key) || empty($this->secret_key)) {
        throw new Exception('API credentials cannot be empty');
      }

      // Build the URI exactly as shown in documentation
      $endpoint = ltrim($endpoint, '/');
      $uri = $this->base_url . '/' . $endpoint;

      // Add appropriate parameter based on endpoint
      if ($endpoint === 'product-data') {
        // Product data endpoint uses locale
        $uri .= (strpos($uri, '?') === false ? '?' : '&') . 'locale=' . $this->locale;
      } else {
        // Other endpoints use storefront
        $uri .= (strpos($uri, '?') === false ? '?' : '&') . 'storefront=' . $this->storefront;
      }

      $timestamp = time();
      $json_body = empty($body) ? '' : wp_json_encode($body);

      // Headers exactly as shown in documentation
      $headers = [
        'accept' => 'application/json',  // Note: lowercase as per curl example
        'Content-Type' => 'application/json',  // Add this header
        'shop-client-key' => $this->client_key,
        'shop-timestamp' => (string)$timestamp,
        'shop-signature' => $this->sign_request($method, $uri, $json_body, $timestamp),
      ];

      $args = [
        'method' => $method,  // Already uppercase from caller
        'headers' => $headers,
        'timeout' => 30,
      ];

      if (!empty($json_body)) {
        $args['body'] = $json_body;
      }

      $response = wp_remote_request($uri, $args);

      if (is_wp_error($response)) {
        throw new Exception($response->get_error_message());
      }

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

      $response_data = json_decode($response_body, true);

      if ($response_code !== 200) {
        $error_message = isset($response_data['message'])
          ? $response_data['message']
          : sprintf('API Error: %d', $response_code);

        throw new Exception($error_message, $response_code);
      }

      return $response_data;
    } catch (Exception $e) {
      throw $e;
    }
  }

  /**
   * Generate HMAC signature for the request
   */
  private function sign_request(string $method, string $uri, string $body, int $timestamp): string
  {
    // Ensure exact string format as per documentation example
    $method = strval($method);  // Ensure it's a string
    $timestamp = strval($timestamp);  // Convert timestamp to string

    // Build signature string exactly as per documentation
    $string = implode("\n", [
      $method,
      $uri,  // URI now includes query parameters
      $body,
      $timestamp,
    ]);

    return hash_hmac('sha256', $string, $this->secret_key);
  }

  /**
   * Validate API credentials format
   */
  protected function validate_credentials(string $client_key, string $secret_key): bool
  {
    // Client Key should be 32 characters
    if (strlen($client_key) !== 32) {
      throw new Exception('Invalid Client Key format. Must be 32 characters.');
    }

    // Secret Key should be 64 characters
    if (strlen($secret_key) !== 64) {
      throw new Exception('Invalid Secret Key format. Must be 64 characters.');
    }

    return true;
  }
}
