<?php

namespace Formatrica\Submission\Integrations\Dispatchers;

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

use Formatrica\Submission\Integrations\Http_Client;
use Formatrica\Submission\Integrations\Integration_Dispatcher_Interface;
use Formatrica\Submission\Rendering\Template_Renderer;
use Formatrica\Support\Secrets;

/**
 * Brevo marketing-list dispatcher (create/update a contact + list membership).
 *
 * This is the MARKETING integration — distinct from the Brevo email-delivery
 * transport under options.email_delivery. Differences from Mailchimp:
 *   - single global endpoint (api.brevo.com/v3/contacts); no datacenter suffix
 *   - auth via the `api-key` request header, not Basic auth
 *   - list membership via `listIds: [int]` in the POST body
 *   - tags serialise into a `TAGS` contact attribute (admin must define TAGS as
 *     a contact attribute in Brevo)
 *   - updateEnabled=true so a re-submit updates the existing contact
 *
 * Runs async via the integration queue.
 */
final class Brevo_Dispatcher implements Integration_Dispatcher_Interface
{
    private const ENDPOINT = 'https://api.brevo.com/v3/contacts';

    private Http_Client $client;
    private Template_Renderer $renderer;

    public function __construct(?Http_Client $client = null, ?Template_Renderer $renderer = null)
    {
        $this->client = $client ?? new Http_Client();
        $this->renderer = $renderer ?? new Template_Renderer();
    }

    public function dispatch(array $settings, array $form, array $payload, array $context, array $field_meta): void
    {
        $encrypted_key = isset($settings['api_key']) ? (string) $settings['api_key'] : '';
        $api_key = $encrypted_key !== '' ? Secrets::decrypt($encrypted_key) : '';
        if ($api_key === '') {
            return;
        }

        $list_id = isset($settings['list_id']) ? trim((string) $settings['list_id']) : '';
        if ($list_id === '' || !ctype_digit($list_id)) {
            // Brevo list ids are numeric; a non-numeric id can't be honoured.
            return;
        }

        $email_field = isset($settings['email_field']) ? (string) $settings['email_field'] : '';
        if ($email_field === '' || !isset($payload[$email_field])) {
            return;
        }

        $email = trim((string) $payload[$email_field]);
        if ($email === '' || !is_email($email)) {
            return;
        }

        $body = [
            'email' => $email,
            'listIds' => [(int) $list_id],
            'updateEnabled' => true,
        ];

        $attributes = [];

        $first_field = isset($settings['first_name_field']) ? (string) $settings['first_name_field'] : '';
        if ($first_field !== '' && isset($payload[$first_field])) {
            $attributes['FIRSTNAME'] = $this->renderer->normalise_value($payload[$first_field]);
        }

        $last_field = isset($settings['last_name_field']) ? (string) $settings['last_name_field'] : '';
        if ($last_field !== '' && isset($payload[$last_field])) {
            $attributes['LASTNAME'] = $this->renderer->normalise_value($payload[$last_field]);
        }

        if (isset($settings['tags']) && is_array($settings['tags']) && !empty($settings['tags'])) {
            $tags = [];
            foreach ($settings['tags'] as $tag) {
                $tag_value = sanitize_text_field((string) $tag);
                if ($tag_value !== '') {
                    $tags[] = $tag_value;
                }
            }
            if (!empty($tags)) {
                $attributes['TAGS'] = implode(', ', $tags);
            }
        }

        if (!empty($attributes)) {
            $body['attributes'] = $attributes;
        }

        /**
         * Filter the Brevo contact payload before it is sent.
         *
         * @param array<string, mixed> $body
         * @param array<string, mixed> $form
         * @param array<string, mixed> $payload
         * @param array<string, mixed> $context
         * @param array<int, array<string, mixed>> $field_meta
         */
        $body = apply_filters('formatrica_brevo_payload', $body, $form, $payload, $context, $field_meta);

        $this->client->send_json(
            self::ENDPOINT,
            $body,
            'brevo',
            $form,
            $payload,
            $context,
            'POST',
            ['api-key' => $api_key]
        );
    }
}
