<?php

declare(strict_types=1);

namespace MailerPress\Actions\Webhooks;

\defined('ABSPATH') || exit;

use MailerPress\Core\Attributes\Action;
use MailerPress\Core\Enums\Tables;
use MailerPress\Core\Webhooks\WebhookManager;

/**
 * Déclenche automatiquement les webhooks sortants lors des événements
 * 
 * @since 1.2.0
 */
class TriggerOutgoingWebhooks
{
    private WebhookManager $webhookManager;

    private array $sentWebhooks = []; // Cache pour éviter d'envoyer plusieurs webhooks pour le même contact

    public function __construct()
    {
        $this->webhookManager = WebhookManager::getInstance();
    }

    /**
     * Vérifie si MailerPress Pro est actif
     * 
     * @return bool True si Pro est actif
     */
    private function isProActive(): bool
    {
        if (!function_exists('is_plugin_active')) {
            require_once \ABSPATH . 'wp-admin/includes/plugin.php';
        }

        return function_exists('is_plugin_active')
            && \is_plugin_active('mailerpress-pro/mailerpress-pro.php');
    }

    /**
     * Déclenche le webhook contact.created
     * Utilise une priorité basse (20) pour s'exécuter après la sauvegarde des champs personnalisés
     * Si les champs personnalisés ne sont pas encore sauvegardés, on attend qu'ils le soient
     */
    #[Action('mailerpress_contact_created', priority: 20)]
    public function onContactCreated(int $contactId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }

        // Vérifier si le webhook a déjà été envoyé (via onCustomFieldAdded)
        $cacheKey = 'contact_' . $contactId;
        if (isset($this->sentWebhooks[$cacheKey])) {
            return;
        }

        // Marquer comme envoyé et envoyer le webhook
        $this->sentWebhooks[$cacheKey] = true;
        $this->sendContactWebhook($contactId, 'contact.created');
    }

    /**
     * Écoute les champs personnalisés ajoutés pour déclencher le webhook si nécessaire
     * Utilise une priorité basse pour s'exécuter après tous les champs
     */
    #[Action('mailerpress_contact_custom_field_added', priority: 99, acceptedArgs: 3)]
    public function onCustomFieldAdded(int $contactId, string $fieldKey, $fieldValue): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }

        // Attendre un peu pour que tous les champs soient sauvegardés
        usleep(100000); // 100ms

        // Vérifier si le webhook a déjà été envoyé
        $cacheKey = 'contact_' . $contactId;
        if (isset($this->sentWebhooks[$cacheKey])) {
            return;
        }

        // Marquer comme envoyé et envoyer le webhook
        $this->sentWebhooks[$cacheKey] = true;
        $this->sendContactWebhook($contactId, 'contact.created');
    }


    /**
     * Déclenche le webhook campaign.sent
     */
    #[Action('mailerpress_campaign_sent', acceptedArgs: 2)]
    public function onCampaignSent(int $campaignId, array $data = []): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }

        // Si $data est vide, utiliser un tableau vide pour éviter les erreurs
        if (empty($data) || !is_array($data)) {
            $data = [];
        }

        $webhookData = array_merge([
            'campaign_id' => $campaignId,
        ], $data);

        $this->webhookManager->triggerOutgoingWebhook('campaign.sent', $webhookData);
    }

    /**
     * Déclenche le webhook contact.updated
     */
    #[Action('mailerpress_contact_updated', acceptedArgs: 1)]
    public function onContactUpdated(int $contactId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }

        $this->sendContactWebhook($contactId, 'contact.updated');
    }

    /**
     * Déclenche le webhook contact.tag.added
     */
    #[Action('mailerpress_contact_tag_added', acceptedArgs: 2)]
    public function onContactTagAdded(int $contactId, int $tagId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }
        global $wpdb;
        $tagsTable = Tables::get(Tables::MAILERPRESS_TAGS);
        $tag = $wpdb->get_row($wpdb->prepare(
            "SELECT tag_id, name FROM {$tagsTable} WHERE tag_id = %d",
            $tagId
        ), \ARRAY_A);

        $contact = $this->getContactBasicData($contactId);
        if (!$contact) {
            return;
        }

        $data = [
            'contact_id' => $contactId,
            'contact_email' => $contact['email'] ?? '',
            'tag_id' => $tagId,
            'tag_name' => $tag['name'] ?? '',
        ];

        $this->webhookManager->triggerOutgoingWebhook('contact.tag.added', $data);
    }

    /**
     * Déclenche le webhook contact.tag.removed
     */
    #[Action('mailerpress_contact_tag_removed', acceptedArgs: 2)]
    public function onContactTagRemoved(int $contactId, int $tagId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }

        global $wpdb;
        $tagsTable = Tables::get(Tables::MAILERPRESS_TAGS);
        $tag = $wpdb->get_row($wpdb->prepare(
            "SELECT tag_id, name FROM {$tagsTable} WHERE tag_id = %d",
            $tagId
        ), \ARRAY_A);

        // Si le tag n'existe plus dans la table tags, on utilise un nom par défaut
        $tagName = $tag['name'] ?? __('Unknown Tag', 'mailerpress');
        if (empty($tagName)) {
            $tagName = sprintf(__('Tag ID: %d', 'mailerpress'), $tagId);
        }

        $contact = $this->getContactBasicData($contactId);
        if (!$contact) {
            return;
        }

        $data = [
            'contact_id' => $contactId,
            'contact_email' => $contact['email'] ?? '',
            'tag_id' => $tagId,
            'tag_name' => $tagName,
        ];

        $this->webhookManager->triggerOutgoingWebhook('contact.tag.removed', $data);
    }

    /**
     * Déclenche le webhook contact.list.added
     */
    #[Action('mailerpress_contact_list_added', acceptedArgs: 2)]
    public function onContactListAdded(int $contactId, int $listId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }
        global $wpdb;
        $listsTable = Tables::get(Tables::MAILERPRESS_LIST);
        $list = $wpdb->get_row($wpdb->prepare(
            "SELECT list_id, name FROM {$listsTable} WHERE list_id = %d",
            $listId
        ), \ARRAY_A);

        $contact = $this->getContactBasicData($contactId);
        if (!$contact) {
            return;
        }

        $data = [
            'contact_id' => $contactId,
            'contact_email' => $contact['email'] ?? '',
            'list_id' => $listId,
            'list_name' => $list['name'] ?? '',
        ];

        $this->webhookManager->triggerOutgoingWebhook('contact.list.added', $data);
    }

    /**
     * Déclenche le webhook contact.list.removed
     */
    #[Action('mailerpress_contact_list_removed', acceptedArgs: 2)]
    public function onContactListRemoved(int $contactId, int $listId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }
        global $wpdb;
        $listsTable = Tables::get(Tables::MAILERPRESS_LIST);
        $list = $wpdb->get_row($wpdb->prepare(
            "SELECT list_id, name FROM {$listsTable} WHERE list_id = %d",
            $listId
        ), \ARRAY_A);

        $contact = $this->getContactBasicData($contactId);
        if (!$contact) {
            return;
        }

        $data = [
            'contact_id' => $contactId,
            'contact_email' => $contact['email'] ?? '',
            'list_id' => $listId,
            'list_name' => $list['name'] ?? '',
        ];

        $this->webhookManager->triggerOutgoingWebhook('contact.list.removed', $data);
    }

    /**
     * Déclenche le webhook contact.custom_field.updated
     */
    #[Action('mailerpress_contact_custom_field_updated', acceptedArgs: 3)]
    public function onContactCustomFieldUpdated(int $contactId, string $fieldKey, $fieldValue): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }
        $contact = $this->getContactBasicData($contactId);
        if (!$contact) {
            return;
        }

        $data = [
            'contact_id' => $contactId,
            'contact_email' => $contact['email'] ?? '',
            'field_key' => $fieldKey,
            'field_value' => $fieldValue,
        ];

        $this->webhookManager->triggerOutgoingWebhook('contact.custom_field.updated', $data);
    }

    /**
     * Déclenche le webhook campaign.created
     */
    #[Action('mailerpress_campaign_created', acceptedArgs: 1)]
    public function onCampaignCreated(int $campaignId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }
        global $wpdb;
        $campaignsTable = Tables::get(Tables::MAILERPRESS_CAMPAIGNS);
        $campaign = $wpdb->get_row($wpdb->prepare(
            "SELECT campaign_id, name, subject, status, campaign_type, created_at FROM {$campaignsTable} WHERE campaign_id = %d",
            intval($campaignId)
        ), \ARRAY_A);

        if (!$campaign) {
            return;
        }

        $data = [
            'campaign_id' => $campaignId,
            'campaign_name' => $campaign['name'] ?? '',
            'campaign_subject' => $campaign['subject'] ?? '',
            'status' => $campaign['status'] ?? '',
            'campaign_type' => $campaign['campaign_type'] ?? '',
            'created_at' => $campaign['created_at'] ?? current_time('mysql'),
        ];

        $this->webhookManager->triggerOutgoingWebhook('campaign.created', $data);
    }

    /**
     * Déclenche le webhook campaign.in_progress
     */
    #[Action('mailerpress_batch_event', priority: 20, acceptedArgs: 3)]
    public function onBatchEvent(string $status, string $campaignId, string $batchId): void
    {
        // Vérifier que Pro est actif
        if (!$this->isProActive()) {
            return;
        }

        if ($status === 'in_progress') {
            global $wpdb;
            $campaignsTable = Tables::get(Tables::MAILERPRESS_CAMPAIGNS);
            $batchesTable = Tables::get(Tables::MAILERPRESS_EMAIL_BATCHES);

            $campaign = $wpdb->get_row($wpdb->prepare(
                "SELECT campaign_id, name, subject FROM {$campaignsTable} WHERE campaign_id = %d",
                (int) $campaignId
            ), \ARRAY_A);

            $batch = $wpdb->get_row($wpdb->prepare(
                "SELECT id, total_emails, sent_emails, error_emails FROM {$batchesTable} WHERE id = %d",
                (int) $batchId
            ), \ARRAY_A);

            if (!$campaign || !$batch) {
                return;
            }

            $data = [
                'campaign_id' => (int) $campaignId,
                'campaign_name' => $campaign['name'] ?? '',
                'campaign_subject' => $campaign['subject'] ?? '',
                'batch_id' => (int) $batchId,
                'total_emails' => isset($batch['total_emails']) ? (int) $batch['total_emails'] : 0,
                'sent_emails' => isset($batch['sent_emails']) ? (int) $batch['sent_emails'] : 0,
                'error_emails' => isset($batch['error_emails']) ? (int) $batch['error_emails'] : 0,
                'progress_percentage' => isset($batch['total_emails']) && $batch['total_emails'] > 0
                    ? round((($batch['sent_emails'] ?? 0) / $batch['total_emails']) * 100, 2)
                    : 0,
            ];

            $this->webhookManager->triggerOutgoingWebhook('campaign.in_progress', $data);
        }
    }

    /**
     * Récupère les données de base d'un contact
     */
    private function getContactBasicData(int $contactId): ?array
    {
        global $wpdb;
        $contactTable = Tables::get(Tables::MAILERPRESS_CONTACT);

        $contact = $wpdb->get_row($wpdb->prepare(
            "SELECT contact_id, email, first_name, last_name, subscription_status FROM {$contactTable} WHERE contact_id = %d",
            $contactId
        ), \ARRAY_A);

        return $contact ?: null;
    }

    /**
     * Envoie le webhook contact avec toutes les données du contact
     * @param int $contactId
     * @param string $eventType Type d'événement (contact.created ou contact.updated)
     */
    private function sendContactWebhook(int $contactId, string $eventType = 'contact.created'): void
    {
        // Récupérer les données du contact
        global $wpdb;
        $contactTable = Tables::get(Tables::MAILERPRESS_CONTACT);

        $contact = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$contactTable} WHERE contact_id = %d",
            $contactId
        ), \ARRAY_A);

        if (!$contact) {
            return;
        }

        // Récupérer les tags du contact
        $contactTagsTable = Tables::get(Tables::CONTACT_TAGS);
        $tagsTable = Tables::get(Tables::MAILERPRESS_TAGS);
        $tags = $wpdb->get_results($wpdb->prepare("
            SELECT t.tag_id, t.name as tag_name
            FROM {$contactTagsTable} ct
            INNER JOIN {$tagsTable} t ON ct.tag_id = t.tag_id
            WHERE ct.contact_id = %d
        ", $contactId), \ARRAY_A);

        $tagsData = [];
        foreach ($tags as $tag) {
            $tagsData[] = [
                'tag_id' => (int) $tag['tag_id'],
                'tag_name' => $tag['tag_name'],
            ];
        }

        // Récupérer les listes du contact
        $contactListsTable = Tables::get(Tables::MAILERPRESS_CONTACT_LIST);
        $listsTable = Tables::get(Tables::MAILERPRESS_LIST);
        $lists = $wpdb->get_results($wpdb->prepare("
            SELECT l.list_id, l.name as list_name
            FROM {$contactListsTable} cl
            INNER JOIN {$listsTable} l ON cl.list_id = l.list_id
            WHERE cl.contact_id = %d
        ", $contactId), \ARRAY_A);

        $listsData = [];
        foreach ($lists as $list) {
            $listsData[] = [
                'list_id' => (int) $list['list_id'],
                'list_name' => $list['list_name'],
            ];
        }

        // Récupérer les champs personnalisés du contact
        $customFieldsTable = Tables::get(Tables::MAILERPRESS_CONTACT_CUSTOM_FIELDS);
        $customFields = $wpdb->get_results($wpdb->prepare("
            SELECT field_key, field_value
            FROM {$customFieldsTable}
            WHERE contact_id = %d
        ", $contactId), \ARRAY_A);

        $customFieldsData = [];
        foreach ($customFields as $field) {
            // Désérialiser la valeur si nécessaire
            $value = maybe_unserialize($field['field_value']);
            $customFieldsData[$field['field_key']] = $value;
        }

        // Préparer les données pour le webhook
        $data = [
            'contact_id' => $contactId,
            'email' => $contact['email'] ?? '',
            'first_name' => $contact['first_name'] ?? '',
            'last_name' => $contact['last_name'] ?? '',
            'subscription_status' => $contact['subscription_status'] ?? '',
            'created_at' => $contact['created_at'] ?? '',
            'updated_at' => $contact['updated_at'] ?? '',
            'tags' => $tagsData,
            'lists' => $listsData,
            'custom_fields' => $customFieldsData,
        ];

        $this->webhookManager->triggerOutgoingWebhook($eventType, $data);
    }
}
