<?php

namespace App\Notifications\Traits;

use App\Models\EmailLog;
use Illuminate\Notifications\Messages\MailMessage;

/**
 * Trait para agregar logging automático a las notificaciones de correo.
 * 
 * Este trait proporciona:
 * - Logging automático de envíos de correo
 * - Registro de intentos fallidos
 * - Soporte para reintentos con backoff exponencial
 * - Metadata personalizada para auditoría
 */
trait LogsEmailNotification
{
    /**
     * The email log instance for this notification
     */
    protected ?EmailLog $emailLog = null;

    /**
     * Maximum retry attempts
     */
    protected int $maxRetries = 3;

    /**
     * Backoff delay in seconds (base for exponential)
     */
    protected int $retryDelay = 60;

    /**
     * Create and store the email log before sending
     */
    protected function createEmailLog(object $notifiable, string $subject, array $metadata = []): EmailLog
    {
        $this->emailLog = EmailLog::createForNotification(
            notificationType: class_basename(static::class),
            notifiable: $notifiable,
            subject: $subject,
            channel: 'mail',
            metadata: array_merge($metadata, [
                'notification_class' => static::class,
                'notifiable_type' => get_class($notifiable),
                'notifiable_id' => $notifiable->getKey(),
            ])
        );

        return $this->emailLog;
    }

    /**
     * Mark the email log as sent
     */
    protected function markEmailSent(): void
    {
        if ($this->emailLog) {
            $this->emailLog->markAsSent();
        }
    }

    /**
     * Mark the email log as failed
     */
    protected function markEmailFailed(string $errorMessage): void
    {
        if ($this->emailLog) {
            $this->emailLog->markAsFailed($errorMessage);
        }
    }

    /**
     * Get the delay for retry based on attempt number
     */
    public function retryAfter(): int
    {
        $attempts = $this->emailLog?->attempts ?? 0;
        
        // Exponential backoff: 60s, 120s, 240s, etc.
        return $this->retryDelay * pow(2, $attempts);
    }

    /**
     * Determine the number of times the job may be attempted.
     */
    public function tries(): int
    {
        return $this->maxRetries;
    }

    /**
     * Get metadata for the email log
     * Override in child classes to add custom metadata
     */
    protected function getEmailLogMetadata(): array
    {
        return [];
    }

    /**
     * Create email log and wrap the mail message
     * Call this at the start of toMail() method
     */
    protected function logAndSendMail(object $notifiable, string $subject, callable $mailBuilder): MailMessage
    {
        // Create the log entry
        $this->createEmailLog($notifiable, $subject, $this->getEmailLogMetadata());

        // Build the mail message
        $mail = $mailBuilder();

        // Add callback to track successful send
        $mail->withSymfonyMessage(function ($message) {
            // This runs when the email is actually sent
            if ($this->emailLog) {
                $this->emailLog->incrementAttempts();
            }
        });

        return $mail;
    }

    /**
     * Handle a job failure.
     */
    public function failed(\Throwable $exception): void
    {
        $this->markEmailFailed($exception->getMessage());
        
        // Log the failure
        \Illuminate\Support\Facades\Log::error('Email notification failed', [
            'notification' => static::class,
            'error' => $exception->getMessage(),
            'email_log_id' => $this->emailLog?->id,
        ]);
    }
}
