<?php
/**
 * File Path: includes/api/esp/class-mbs-esp-activecampaign.php
 * ActiveCampaign ESP Adapter -- My Book Showroom
 * Sprint F-026: Email Channel Integration.
 * @package My_Book_Showroom
 * @since   1.1.0
 */
if ( ! defined( 'ABSPATH' ) ) { exit; }

class MBS_ESP_ActiveCampaign extends MBS_ESP_Adapter_Base { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix
	private string $api_key; private string $account_url;
	public function __construct( string $api_key, string $account_url = '' ) {
		$this->api_key = $api_key;
		// SA-H4: Validate account_url before storing — prevents SSRF via admin-supplied URL.
		$trimmed_url = rtrim( $account_url, '/' );
		if ( '' !== $trimmed_url && ( ! wp_http_validate_url( $trimmed_url ) || ! in_array( wp_parse_url( $trimmed_url, PHP_URL_SCHEME ), array( 'https', 'http' ), true ) ) ) {
			$trimmed_url = ''; // Reject non-HTTP(S) or structurally invalid URLs.
		}
		$this->account_url = $trimmed_url;
	}
	protected function endpoint_url( string $endpoint ): string { return $this->account_url . '/api/3/' . $endpoint; }
	public function connect(): bool {
		$r = $this->get( 'account' );
		return ! is_wp_error( $r ) && 200 === (int) wp_remote_retrieve_response_code( $r );
	}
	public function get_lists(): array {
		$r = $this->get( 'lists?limit=100' );
		if ( is_wp_error( $r ) ) { return array(); }
		$b = json_decode( wp_remote_retrieve_body( $r ), true );
		if ( empty( $b['lists'] ) ) { return array(); }
		$out = array();
		foreach ( $b['lists'] as $lst ) { $out[] = array( 'id' => (string) $lst['id'], 'name' => (string) $lst['name'] ); }
		return $out;
	}
	public function subscribe( string $email, string $name, string $list_id, bool $double_optin ): bool {
		// Step 1: Create/update contact.
		$parts   = explode( ' ', $name, 2 );
		$contact = array( 'contact' => array( 'email' => $email, 'firstName' => $parts[0], 'lastName' => isset( $parts[1] ) ? $parts[1] : '' ) );
		$r1 = $this->post( 'contacts', $contact );
		if ( is_wp_error( $r1 ) ) { return false; }
		$r1_code = (int) wp_remote_retrieve_response_code( $r1 );
		if ( $r1_code < 200 || $r1_code >= 300 ) { return false; }
		$r1_body        = json_decode( wp_remote_retrieve_body( $r1 ), true );
		$contact_id = $r1_body['contact']['id'] ?? '';
		if ( '' === $contact_id ) { return false; }
		// Step 2: Add contact to list.
		$r2 = $this->post( 'contactLists', array( 'contactList' => array( 'list' => (int) $list_id, 'contact' => (int) $contact_id, 'status' => $double_optin ? 0 : 1 ) ) );
		if ( is_wp_error( $r2 ) ) { return false; }
		$r2_code = (int) wp_remote_retrieve_response_code( $r2 );
		return $r2_code >= 200 && $r2_code < 300;
	}
	public function tag_contact( string $email, array $tags, string $list_id ): bool {
		if ( empty( $tags ) ) { return true; }
		// Find contact by email.
		$search = $this->get( 'contacts?email=' . rawurlencode( $email ) );
		if ( is_wp_error( $search ) ) { return false; }
		$sb = json_decode( wp_remote_retrieve_body( $search ), true );
		$contact_id = $sb['contacts'][0]['id'] ?? '';
		if ( '' === $contact_id ) { return false; }
		$all_ok = true;
		foreach ( $tags as $tag ) {
			// Find or create tag.
			$tag_create = $this->post( 'tags', array( 'tag' => array( 'tag' => (string) $tag, 'tagType' => 'contact' ) ) );
			if ( is_wp_error( $tag_create ) ) { $all_ok = false; continue; }
			$tb = json_decode( wp_remote_retrieve_body( $tag_create ), true );
			$tag_id = $tb['tag']['id'] ?? '';
			if ( '' === $tag_id ) { $all_ok = false; continue; }
			$ct = $this->post( 'contactTags', array( 'contactTag' => array( 'contact' => $contact_id, 'tag' => $tag_id ) ) );
			if ( is_wp_error( $ct ) ) { $all_ok = false; }
		}
		return $all_ok;
	}
	public function supports_tags(): bool { return true; }
	public function create_campaign( string $subject, string $body_html, string $list_id ): ?string {
		$sender_name  = mbs_get_setting( 'email', 'from_name', '' );
		if ( empty( $sender_name ) ) { $sender_name = get_bloginfo( 'name' ); }
		$sender_email = mbs_get_setting( 'email', 'reply_to', '' );
		if ( empty( $sender_email ) ) { $sender_email = get_option( 'admin_email' ); }
		$payload = array( 'campaign' => array(
			'type' => 'single', 'name' => $subject, 'subject' => $subject,
			'fromname' => $sender_name, 'fromemail' => $sender_email,
			'reply2' => '', 'toname' => '',
			'message' => array( 'html' => $body_html, 'text' => wp_strip_all_tags( $body_html ) ),
			'bounceid' => 0, 'unsubscribid' => 0,
		) );
		$r = $this->post( 'campaigns', $payload, self::TIMEOUT_CAMPAIGN );
		if ( is_wp_error( $r ) ) { return null; }
		if ( (int) wp_remote_retrieve_response_code( $r ) < 200 || (int) wp_remote_retrieve_response_code( $r ) >= 300 ) { return null; }
		$b = json_decode( wp_remote_retrieve_body( $r ), true );
		return isset( $b['campaign']['id'] ) ? (string) $b['campaign']['id'] : null;
	}
	public function send_campaign( string $campaign_id ): bool {
		// ActiveCampaign sends via campaign action.
		$endpoint = 'campaigns/' . rawurlencode( $campaign_id );
		// Use PUT to set status=1 (active/send).
		$r = $this->request( 'PUT', $endpoint, array( 'campaign' => array( 'status' => 1 ) ), self::TIMEOUT_CAMPAIGN );
		return ! is_wp_error( $r ) && (int) wp_remote_retrieve_response_code( $r ) >= 200 && (int) wp_remote_retrieve_response_code( $r ) < 300;
	}
	public function supports_campaigns(): bool { return true; }
	protected function auth_headers(): array { return array( 'Api-Token' => $this->api_key ); }
}
