<?php
/**
 * Mailjet API wrapper.
 *
 * @package    WPFMJ
 * @subpackage WPFMJ/includes
 */

class WPFMJ_Mailjet_API {

    /**
     * API base URL.
     */
    private $api_url = 'https://api.mailjet.com/v3';

    /**
     * API key.
     */
    private $api_key;

    /**
     * API secret.
     */
    private $api_secret;

    /**
     * Constructor.
     */
    public function __construct($api_key = '', $api_secret = '') {
        $this->api_key = $api_key;
        $this->api_secret = $api_secret;
    }

    /**
     * Test API connection.
     */
    public function test_connection() {
        $response = $this->request('GET', '/contact');
        return !is_wp_error($response);
    }

    /**
     * Get all contact lists.
     */
    public function get_lists() {
        $response = $this->request('GET', '/contactslist?Limit=1000');
        
        if (is_wp_error($response)) {
            return $response;
        }

        return isset($response['Data']) ? $response['Data'] : array();
    }

    /**
     * Add contact to list(s).
     */
    public function add_contact_to_lists($email, $lists, $properties = array()) {
        // Validate inputs
        if (empty($email) || !is_email($email)) {
            return new WP_Error('invalid_email', 'Invalid email address provided');
        }

        if (!is_array($lists) || empty($lists)) {
            return new WP_Error('invalid_lists', 'Lists must be a non-empty array');
        }

        // First, ensure contact exists
        $contact = $this->get_or_create_contact($email, $properties);

        if (is_wp_error($contact)) {
            return $contact;
        }

        // Validate contact response structure
        if (!isset($contact['ID'])) {
            return new WP_Error('invalid_contact_response', 'Contact response missing ID field');
        }

        $contact_id = $contact['ID'];
        $results = array();

        // Add contact to each list
        foreach ($lists as $list_id) {
            // Validate list ID
            $list_id = absint($list_id);
            if ($list_id === 0) {
                $results['invalid'] = new WP_Error('invalid_list_id', 'Invalid list ID');
                continue;
            }

            $result = $this->add_contact_to_list($contact_id, $list_id);
            $results[$list_id] = $result;
        }

        return $results;
    }

    /**
     * Get or create a contact.
     */
    private function get_or_create_contact($email, $properties = array()) {
        // Try to get existing contact
        $response = $this->request('GET', '/contact/' . rawurlencode($email));
        
        if (!is_wp_error($response) && isset($response['Data'][0])) {
            // Contact exists, update properties if provided
            if (!empty($properties)) {
                $this->update_contact($email, $properties);
            }
            return $response['Data'][0];
        }

        // Create new contact
        $data = array('Email' => $email);
        
        if (!empty($properties)) {
            $data['Properties'] = $properties;
        }

        $response = $this->request('POST', '/contact', $data);
        
        if (is_wp_error($response)) {
            return $response;
        }

        return isset($response['Data'][0]) ? $response['Data'][0] : new WP_Error('contact_creation_failed', 'Failed to create contact');
    }

    /**
     * Update contact properties.
     */
    private function update_contact($email, $properties) {
        $data = array('Data' => $properties);
        return $this->request('PUT', '/contactdata/' . rawurlencode($email), $data);
    }

    /**
     * Add contact to a specific list.
     */
    private function add_contact_to_list($contact_id, $list_id) {
        $data = array(
            'ContactID' => $contact_id,
            'ListID' => $list_id,
            'IsActive' => true
        );

        return $this->request('POST', '/contactslist/' . $list_id . '/managecontact', $data);
    }

    /**
     * Make API request with rate limiting.
     */
    private function request($method, $endpoint, $data = array()) {
        // Rate limiting: configurable via filter, default 60 requests per minute
        $rate_limit = apply_filters('wpfmj_api_rate_limit', 60);
        $rate_limit = max(10, min(300, absint($rate_limit))); // Clamp between 10-300
        
        $rate_limit_key = 'wpfmj_api_rate_' . md5($this->api_key);
        $requests = get_transient($rate_limit_key);
        
        if ($requests === false) {
            $requests = 0;
        }
        
        if ($requests >= $rate_limit) {
            return new WP_Error('rate_limit_exceeded', sprintf(
                'API rate limit exceeded (%d requests per minute). Please wait a moment and try again.',
                $rate_limit
            ));
        }
        
        // Increment request count
        set_transient($rate_limit_key, $requests + 1, 60);
        
        $url = $this->api_url . $endpoint;
        
        $args = array(
            'method' => $method,
            'headers' => array(
                'Content-Type' => 'application/json',
                'Authorization' => 'Basic ' . base64_encode($this->api_key . ':' . $this->api_secret)
            ),
            'timeout' => 30,
            'sslverify' => true
        );

        if ($method === 'POST' || $method === 'PUT') {
            $args['body'] = wp_json_encode($data);
        }

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

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

        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);

        // Validate JSON response
        $json = json_decode($body, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return new WP_Error(
                'mailjet_json_error',
                sprintf('Invalid JSON response from Mailjet API: %s', json_last_error_msg()),
                array('status' => $code, 'body' => substr($body, 0, 200))
            );
        }

        if ($code >= 400) {
            $message = isset($json['ErrorMessage']) ? sanitize_text_field($json['ErrorMessage']) : 'API request failed';
            return new WP_Error('mailjet_api_error', $message, array('status' => $code));
        }

        return $json;
    }
}
