<?php

namespace GriffinForms\Includes\Pipelines\Handlers;

use GriffinForms\Includes\Pipelines\PostSubmissionHandlerInterface;
use GriffinForms\Includes\Pipelines\JobRepository;

class MailQueueHandler implements PostSubmissionHandlerInterface
{
    /** @var JobRepository */
    protected $repository;

    public function __construct()
    {
        $this->repository = JobRepository::getInstance();
    }

    public function getId(): string
    {
        return 'mail_queue';
    }

    public function getPriority(): int
    {
        return 100;
    }

    public function supports(array $context): bool
    {
        // Yield to NotificationDispatchHandler when the form has v2 notifications saved.
        // This prevents double-sends during the transition period.
        // TODO: retire this guard (and this handler) after NotificationDispatchHandler is validated in production.
        $form = $context['form_object'] ?? null;
        if ($form !== null) {
            $notifications_raw = is_object($form) && method_exists($form, 'getProp')
                ? $form->getProp('notifications')
                : (is_array($form) ? ($form['notifications'] ?? null) : null);
            if (!empty($notifications_raw)) {
                return false;
            }
        }

        $meta = $context['mail_meta'] ?? [];
        if (!is_array($meta)) {
            return false;
        }

        if (empty($meta['alert_emails']) && empty($meta['autoresponder_mappings'])) {
            return false;
        }

        $settings = \GriffinForms\Settings::getInstance();
        $system = sanitize_text_field($settings->getOption('mailing_system', 'server_mail'));

        if ($system === 'mailgun') {
            return \GriffinForms\Includes\Integrations\Mailgun\Helpers::isConfigured();
        }

        if ($system === 'sendgrid') {
            $sendgrid_key = $settings->getOption('sendgrid_api_key');
            return !empty($sendgrid_key);
        }

        if ($system === 'custom_smtp') {
            $smtp_host = $settings->getOption('smtp_host');
            $smtp_port = $settings->getOption('smtp_port');
            return !empty($smtp_host) && !empty($smtp_port);
        }

        return $system === 'server_mail';
    }

    public function handle(array $context): void
    {
        $submission_id = isset($context['submission_id']) ? (int) $context['submission_id'] : 0;
        $form_id = isset($context['form_id']) ? (int) $context['form_id'] : 0;

        if ($submission_id <= 0 || $form_id <= 0) {
            return;
        }

        $meta = $context['mail_meta'] ?? [];
        $this->queueAdminAlerts($meta['alert_emails'] ?? [], $submission_id, $form_id);
        $this->queueAutoresponders($meta, $submission_id, $form_id);
    }

    private function queueAdminAlerts(array $recipients, int $submission_id, int $form_id): void
    {
        if (empty($recipients)) {
            return;
        }

        $keys = array_keys($recipients);
        $is_assoc = $keys !== range(0, count($recipients) - 1);

        if ($is_assoc) {
            foreach ($recipients as $email => $message_id) {
                $email = sanitize_email($email);
                if (empty($email)) {
                    continue;
                }
                $this->repository->enqueue(
                    'mail_admin_alert',
                    'mailer',
                    $submission_id,
                    $form_id,
                    [
                        'recipient' => $email,
                        'message_id' => (int) $message_id,
                    ],
                    10
                );
            }
            return;
        }

        foreach ($recipients as $recipient) {
            $email = sanitize_email($recipient);
            if (empty($email)) {
                continue;
            }

            $this->repository->enqueue(
                'mail_admin_alert',
                'mailer',
                $submission_id,
                $form_id,
                [ 'recipient' => $email ],
                10
            );
        }
    }

    private function queueAutoresponders(array $meta, int $submission_id, int $form_id): void
    {
        $mappings = $this->normalizeMappings($meta['autoresponder_mappings'] ?? []);
        if (empty($mappings)) {
            return;
        }

        $field_value_map = isset($meta['field_value_map']) && is_array($meta['field_value_map'])
            ? $meta['field_value_map']
            : [];

        foreach ($mappings as $mapping) {
            $field_id = isset($mapping['email_field_id']) ? (string) $mapping['email_field_id'] : '';
            $message_id = isset($mapping['message_id']) ? (int) $mapping['message_id'] : 0;

            if ($field_id === '' || $message_id <= 0) {
                continue;
            }

            $values = $field_value_map[$field_id] ?? $field_value_map[(int) $field_id] ?? [];
            foreach ($values as $value) {
                $email = sanitize_email($value);
                if (empty($email)) {
                    continue;
                }

                $this->repository->enqueue(
                    'mail_autoresponder',
                    'mailer',
                    $submission_id,
                    $form_id,
                    [
                        'recipient'  => $email,
                        'message_id' => $message_id,
                    ],
                    5
                );
            }
        }
    }

    private function normalizeMappings($mappings): array
    {
        if (is_string($mappings)) {
            $decoded = json_decode($mappings, true);
            if (is_array($decoded)) {
                $mappings = $decoded;
            }
        }

        return is_array($mappings) ? $mappings : [];
    }
}
