<?php
/**
 * Kit API Client
 *
 * @package Sequensy\Integrations\Kit
 * @since 1.0.0
 */

declare(strict_types=1);

namespace Sequensy\Integrations\Kit;

use Sequensy\Integrations\AbstractApiClient;
use WP_Error;

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

/**
 * Class KitApi
 *
 * API client for Kit's (ConvertKit) REST API v4.
 */
class KitApi extends AbstractApiClient {

	/**
	 * Kit API key.
	 *
	 * @var string
	 */
	private string $api_key;

	/**
	 * Constructor.
	 *
	 * @param string $api_key Kit API key.
	 */
	public function __construct( string $api_key ) {
		$this->api_key = $api_key;
		$this->init_circuit_breaker();
	}

	/**
	 * {@inheritDoc}
	 */
	protected function get_base_url(): string {
		return 'https://api.kit.com/v4/';
	}

	/**
	 * {@inheritDoc}
	 */
	protected function get_auth_headers(): array {
		return array(
			'X-Kit-Api-Key' => $this->api_key,
		);
	}

	/**
	 * {@inheritDoc}
	 */
	protected function get_error_code(): string {
		return 'kit_api_error';
	}

	/**
	 * {@inheritDoc}
	 *
	 * @param array|null $decoded     Decoded JSON response body.
	 * @param int        $status_code HTTP status code.
	 */
	protected function parse_error_message( ?array $decoded, int $status_code ): string {
		if ( isset( $decoded['errors'] ) && is_array( $decoded['errors'] ) && ! empty( $decoded['errors'] ) ) {
			return implode( '; ', $decoded['errors'] );
		}

		if ( isset( $decoded['message'] ) ) {
			return $decoded['message'];
		}

		return sprintf(
			/* translators: %d: HTTP status code */
			__( 'Kit API error (HTTP %d)', 'sequensy' ),
			$status_code
		);
	}

	/**
	 * {@inheritDoc}
	 */
	protected function get_circuit_key(): string {
		return 'kit_api';
	}

	/**
	 * Validate API credentials by fetching subscribers.
	 *
	 * Uses a lightweight GET /subscribers call to verify the API key is valid.
	 *
	 * @return array|WP_Error Validation result or error.
	 */
	public function validate_credentials(): array|WP_Error {
		return $this->request( 'GET', 'subscribers' );
	}

	/**
	 * Create a new subscriber.
	 *
	 * @param array $data Subscriber data (email_address, first_name, etc.).
	 * @return array|WP_Error Created subscriber data or error.
	 */
	public function create_subscriber( array $data ): array|WP_Error {
		return $this->request( 'POST', 'subscribers', $data );
	}

	/**
	 * Update an existing subscriber.
	 *
	 * @param int   $subscriber_id Subscriber ID.
	 * @param array $data          Subscriber data to update.
	 * @return array|WP_Error Updated subscriber data or error.
	 */
	public function update_subscriber( int $subscriber_id, array $data ): array|WP_Error {
		return $this->request( 'PATCH', 'subscribers/' . $subscriber_id, $data );
	}

	/**
	 * Unsubscribe a subscriber.
	 *
	 * @param int $subscriber_id Subscriber ID.
	 * @return array|WP_Error Unsubscribe result or error.
	 */
	public function unsubscribe( int $subscriber_id ): array|WP_Error {
		return $this->request( 'POST', 'subscribers/' . $subscriber_id . '/unsubscribe' );
	}

	/**
	 * Get a subscriber by email address.
	 *
	 * @param string $email Email address to search for.
	 * @return array|WP_Error Subscriber data or error.
	 */
	public function get_subscriber_by_email( string $email ): array|WP_Error {
		return $this->request( 'GET', 'subscribers?email_address=' . rawurlencode( $email ) );
	}

	/**
	 * Add a tag to a subscriber.
	 *
	 * @param int $subscriber_id Subscriber ID.
	 * @param int $tag_id        Tag ID.
	 * @return array|WP_Error Tag assignment result or error.
	 */
	public function add_tag( int $subscriber_id, int $tag_id ): array|WP_Error {
		return $this->request(
			'POST',
			'subscribers/' . $subscriber_id . '/tags',
			array(
				'tag_id' => $tag_id,
			)
		);
	}

	/**
	 * Remove a tag from a subscriber.
	 *
	 * @param int $subscriber_id Subscriber ID.
	 * @param int $tag_id        Tag ID.
	 * @return array|WP_Error Tag removal result or error.
	 */
	public function remove_tag( int $subscriber_id, int $tag_id ): array|WP_Error {
		return $this->request( 'DELETE', 'subscribers/' . $subscriber_id . '/tags/' . $tag_id );
	}

	/**
	 * Add a subscriber to a form.
	 *
	 * @param int $form_id       Form ID.
	 * @param int $subscriber_id Subscriber ID.
	 * @return array|WP_Error Form subscription result or error.
	 */
	public function add_to_form( int $form_id, int $subscriber_id ): array|WP_Error {
		return $this->request(
			'POST',
			'forms/' . $form_id . '/subscribers',
			array(
				'subscriber_id' => $subscriber_id,
			)
		);
	}

	/**
	 * Add a subscriber to a sequence.
	 *
	 * @param int $sequence_id   Sequence ID.
	 * @param int $subscriber_id Subscriber ID.
	 * @return array|WP_Error Sequence subscription result or error.
	 */
	public function add_to_sequence( int $sequence_id, int $subscriber_id ): array|WP_Error {
		return $this->request(
			'POST',
			'sequences/' . $sequence_id . '/subscribers',
			array(
				'subscriber_id' => $subscriber_id,
			)
		);
	}

	/**
	 * Create a broadcast.
	 *
	 * @param array $data Broadcast data (subject, content, etc.).
	 * @return array|WP_Error Created broadcast data or error.
	 */
	public function create_broadcast( array $data ): array|WP_Error {
		return $this->request( 'POST', 'broadcasts', $data );
	}

	/**
	 * List all tags.
	 *
	 * @return array|WP_Error Tags list or error.
	 */
	public function list_tags(): array|WP_Error {
		return $this->request( 'GET', 'tags' );
	}

	/**
	 * List all forms.
	 *
	 * @return array|WP_Error Forms list or error.
	 */
	public function list_forms(): array|WP_Error {
		return $this->request( 'GET', 'forms' );
	}

	/**
	 * List all sequences.
	 *
	 * @return array|WP_Error Sequences list or error.
	 */
	public function list_sequences(): array|WP_Error {
		return $this->request( 'GET', 'sequences' );
	}

	/**
	 * List all segments.
	 *
	 * @return array|WP_Error Segments list or error.
	 */
	public function list_segments(): array|WP_Error {
		return $this->request( 'GET', 'segments' );
	}

	/**
	 * List all email templates.
	 *
	 * @return array|WP_Error Email templates list or error.
	 */
	public function list_email_templates(): array|WP_Error {
		return $this->request( 'GET', 'email_templates' );
	}
}
