<?php
/**
 * File Path: includes/api/esp/class-mbs-esp-convertkit.php
 *
 * ConvertKit (Kit) ESP Adapter -- My Book Showroom
 *
 * API: Kit API v4 (api.kit.com/v4).
 * Auth: Bearer token (API key is the bearer token).
 * Note: ConvertKit is subscriber-centric -- no traditional lists.
 * get_lists() returns forms, labeled "Form: {name}".
 *
 * Sprint F-026: Email Channel Integration.
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Api/Esp
 * @since      1.1.0
 */

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

class MBS_ESP_ConvertKit extends MBS_ESP_Adapter_Base { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	protected const BASE_URL = 'https://api.kit.com/v4/';

	/** @var string */
	private string $api_key;

	public function __construct( string $api_key ) {
		$this->api_key = $api_key;
	}

	/** {@inheritDoc} */
	public function connect(): bool {
		// Fetch account info to test credentials.
		$response = $this->get( 'account' );
		if ( is_wp_error( $response ) ) { return false; }
		return 200 === (int) wp_remote_retrieve_response_code( $response );
	}

	/** {@inheritDoc} */
	public function get_lists(): array {
		// ConvertKit has no traditional lists -- return forms as selectable 'lists'.
		$response = $this->get( 'forms?per_page=500' );
		if ( is_wp_error( $response ) ) { return array(); }
		$body = json_decode( wp_remote_retrieve_body( $response ), true );
		if ( empty( $body['forms'] ) || ! is_array( $body['forms'] ) ) { return array(); }
		$result = array();
		foreach ( $body['forms'] as $form ) {
			$result[] = array( 'id' => (string) $form['id'], 'name' => 'Form: ' . (string) $form['name'] );
		}
		return $result;
	}

	/** {@inheritDoc} */
	public function subscribe( string $email, string $name, string $list_id, bool $double_optin ): bool {
		// Step 1: Create/update subscriber.
		$sub_payload = array( 'email_address' => $email );
		if ( '' !== $name ) {
			$sub_payload['first_name'] = $name;
		}
		$sub_resp = $this->post( 'subscribers', $sub_payload );
		if ( is_wp_error( $sub_resp ) ) { return false; }
		$sub_code = (int) wp_remote_retrieve_response_code( $sub_resp );
		if ( $sub_code < 200 || $sub_code >= 300 ) { return false; }
		// Step 2: Add subscriber to form (list_id = form ID).
		if ( '' !== $list_id ) {
			$form_endpoint = 'forms/' . rawurlencode( $list_id ) . '/subscribers';
			$form_resp = $this->post( $form_endpoint, array( 'email_address' => $email ) );
			// A non-error response is considered success (200 or 201).
			if ( is_wp_error( $form_resp ) ) { return false; }
		}
		return true;
	}

	/** {@inheritDoc} */
	public function tag_contact( string $email, array $tags, string $list_id ): bool {
		if ( empty( $tags ) ) { return true; }
		// Find subscriber ID first.
		$sub_resp = $this->get( 'subscribers?email_address=' . rawurlencode( $email ) . '&per_page=1' );
		if ( is_wp_error( $sub_resp ) ) { return false; }
		$sub_body = json_decode( wp_remote_retrieve_body( $sub_resp ), true );
		$subscriber_id = $sub_body['subscribers'][0]['id'] ?? '';
		if ( '' === $subscriber_id ) { return false; }
		$all_ok = true;
		foreach ( $tags as $tag ) {
			// Create tag if not exists.
			$tag_create_resp = $this->post( 'tags', array( 'name' => (string) $tag ) );
			if ( is_wp_error( $tag_create_resp ) ) { $all_ok = false; continue; }
			$tag_body = json_decode( wp_remote_retrieve_body( $tag_create_resp ), true );
			$tag_id = $tag_body['tag']['id'] ?? '';
			if ( '' === $tag_id ) { $all_ok = false; continue; }
			// Tag the subscriber.
			$tag_sub_endpoint = 'subscribers/' . rawurlencode( $subscriber_id ) . '/tags';
			$tag_sub_resp = $this->post( $tag_sub_endpoint, array( 'tag' => $tag_id ) );
			if ( is_wp_error( $tag_sub_resp ) ) { $all_ok = false; }
		}
		return $all_ok;
	}

	/** {@inheritDoc} */
	public function supports_tags(): bool { return true; }

	/** {@inheritDoc} */
	public function create_campaign( string $subject, string $body_html, string $list_id ): ?string {
		// ConvertKit uses "broadcasts" for email sends.
		$payload = array(
			'subject'       => $subject,
			'content'       => $body_html,
			'public'        => false,
		);
		$response = $this->post( 'broadcasts', $payload, self::TIMEOUT_CAMPAIGN );
		if ( is_wp_error( $response ) ) { return null; }
		$code = (int) wp_remote_retrieve_response_code( $response );
		if ( $code < 200 || $code >= 300 ) { return null; }
		$body = json_decode( wp_remote_retrieve_body( $response ), true );
		return isset( $body['broadcast']['id'] ) ? (string) $body['broadcast']['id'] : null;
	}

	/** {@inheritDoc} */
	public function send_campaign( string $campaign_id ): bool {
		$endpoint = 'broadcasts/' . rawurlencode( $campaign_id ) . '/send';
		$response = $this->post( $endpoint, array(), self::TIMEOUT_CAMPAIGN );
		if ( is_wp_error( $response ) ) { return false; }
		$code = (int) wp_remote_retrieve_response_code( $response );
		return $code >= 200 && $code < 300;
	}

	/** {@inheritDoc} */
	public function supports_campaigns(): bool { return true; }

	// -------------------------------------------------------------------------
	// Private HTTP helpers
	// -------------------------------------------------------------------------

	protected function auth_headers(): array {
		return array( 'Authorization' => 'Bearer ' . $this->api_key );
	}
}
