<?php
/**
 * File Path: includes/api/esp/class-mbs-esp-mailerlite.php
 *
 * MailerLite ESP Adapter -- My Book Showroom
 *
 * API: MailerLite API v2 (connect.mailerlite.com/api).
 * Auth: Bearer token (API key is the bearer token).
 * Lists: MailerLite calls them "groups".
 *
 * 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_MailerLite 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://connect.mailerlite.com/api/';

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

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

	/** {@inheritDoc} */
	public function connect(): bool {
		// Fetch first page of groups to verify credentials.
		$response = $this->get( 'groups?limit=1' );
		if ( is_wp_error( $response ) ) { return false; }
		return 200 === (int) wp_remote_retrieve_response_code( $response );
	}

	/** {@inheritDoc} */
	public function get_lists(): array {
		$response = $this->get( 'groups?limit=100' );
		if ( is_wp_error( $response ) ) { return array(); }
		$body = json_decode( wp_remote_retrieve_body( $response ), true );
		if ( empty( $body['data'] ) || ! is_array( $body['data'] ) ) { return array(); }
		$result = array();
		foreach ( $body['data'] as $group ) {
			$result[] = array( 'id' => (string) $group['id'], 'name' => (string) $group['name'] );
		}
		return $result;
	}

	/** {@inheritDoc} */
	public function subscribe( string $email, string $name, string $list_id, bool $double_optin ): bool {
		$payload = array( 'email' => $email );
		if ( '' !== $name ) {
			$payload['fields'] = array( 'name' => $name );
		}
		if ( ! $double_optin ) {
			// opted_in_at triggers immediate subscription (no confirmation email).
			$payload['opted_in_at'] = gmdate( 'Y-m-d H:i:s' );
		}
		// groups[] array tells MailerLite which group(s) to add the subscriber to.
		if ( '' !== $list_id ) {
			$payload['groups'] = array( $list_id );
		}
		$response = $this->post( 'subscribers', $payload );
		if ( is_wp_error( $response ) ) { return false; }
		$code = (int) wp_remote_retrieve_response_code( $response );
		return $code >= 200 && $code < 300;
	}

	/** {@inheritDoc} */
	public function tag_contact( string $email, array $tags, string $list_id ): bool {
		// MailerLite v2 uses groups as tags. For each tag:
		// 1. Find or create a group with that name.
		// 2. Look up subscriber by email to get their ID.
		// 3. POST to /subscribers/{id}/groups to add them.
		if ( empty( $tags ) ) { return true; }
		// Find subscriber ID.
		$sub_response = $this->get( 'subscribers?filter[email]=' . rawurlencode( $email ) . '&limit=1' );
		if ( is_wp_error( $sub_response ) ) { return false; }
		$sub_body = json_decode( wp_remote_retrieve_body( $sub_response ), true );
		$subscriber_id = $sub_body['data'][0]['id'] ?? '';
		if ( '' === $subscriber_id ) { return false; }
		$all_ok = true;
		foreach ( $tags as $tag ) {
			$group_id = $this->find_or_create_group( (string) $tag );
			if ( '' === $group_id ) { $all_ok = false; continue; }
			$endpoint = 'subscribers/' . rawurlencode( $subscriber_id ) . '/groups';
			$resp = $this->post( $endpoint, array( 'group' => $group_id ) );
			if ( is_wp_error( $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 {
		$payload = array(
			'name'     => $subject,
			'type'     => 'regular',
			'status'   => 'draft',
			'subject'  => $subject,
			'groups'   => array( $list_id ),
		);
		$from_name  = mbs_get_setting( 'email', 'from_name', '' );
		if ( empty( $from_name ) ) {
			$from_name = get_bloginfo( 'name' );
		}
		$reply_to   = mbs_get_setting( 'email', 'reply_to', '' );
		if ( empty( $reply_to ) ) {
			$reply_to = get_option( 'admin_email', '' );
		}
		$payload['emails'] = array(
				array(
					'subject'   => $subject,
					'from_name' => $from_name,
					'from'      => $reply_to,
					'content'   => array( 'html' => $body_html ),
				),
		);
		$response = $this->post( 'campaigns', $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 $body['data']['id'] ?? null;
	}

	/** {@inheritDoc} */
	public function send_campaign( string $campaign_id ): bool {
		$endpoint = 'campaigns/' . rawurlencode( $campaign_id ) . '/schedule';
		// Schedule immediately (MailerLite v2 uses schedule endpoint for send).
		$payload  = array( 'delivery' => 'instant' );
		$response = $this->post( $endpoint, $payload, 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 helpers
	// -------------------------------------------------------------------------

	/** Find a group by name, or create it, returning the group ID. */
	private function find_or_create_group( string $name ): string {
		$search = $this->get( 'groups?filter[name]=' . rawurlencode( $name ) . '&limit=1' );
		if ( ! is_wp_error( $search ) ) {
			$body  = json_decode( wp_remote_retrieve_body( $search ), true );
			$gid = $body['data'][0]['id'] ?? '';
			if ( '' !== $gid ) { return (string) $gid; }
		}
		// Group does not exist -- create it.
		$create = $this->post( 'groups', array( 'name' => $name ) );
		if ( is_wp_error( $create ) ) { return ''; }
		$body = json_decode( wp_remote_retrieve_body( $create ), true );
		return (string) ( $body['data']['id'] ?? '' );
	}

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