<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

/**
 * EmailLog Model
 * 
 * Stores logs of all email operations for debugging and audit purposes.
 * Includes SMTP sends, IMAP receives, and connection tests.
 * 
 * Features:
 * - JSON response storage for detailed debugging
 * - Execution time tracking for performance monitoring
 * - Query scopes for easy filtering
 * 
 * @property int $id
 * @property string $type
 * @property string|null $recipient
 * @property string|null $subject
 * @property string $status
 * @property array|null $response_body
 * @property string|null $error_message
 * @property int $execution_time_ms
 * @property \Illuminate\Support\Carbon $created_at
 */
class EmailLog extends Model
{
    use HasFactory;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'email_logs';

    /**
     * Indicates if the model should be timestamped.
     * Logs only have created_at, not updated_at.
     *
     * @var bool
     */
    public $timestamps = false;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'type',
        'recipient',
        'subject',
        'status',
        'response_body',
        'error_message',
        'execution_time_ms',
        'created_at',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'response_body' => 'array',
        'execution_time_ms' => 'integer',
        'created_at' => 'datetime',
    ];

    /**
     * Log type constants.
     */
    const TYPE_SMTP_SEND = 'smtp_send';
    const TYPE_IMAP_RECEIVE = 'imap_receive';
    const TYPE_TEST = 'test';

    /**
     * Status constants.
     */
    const STATUS_SUCCESS = 'success';
    const STATUS_FAILED = 'failed';

    /**
     * Validation rules for email log.
     *
     * @var array<string, string>
     */
    public static array $validationRules = [
        'type' => 'required|in:smtp_send,imap_receive,test',
        'recipient' => 'nullable|string|max:191',
        'subject' => 'nullable|string|max:191',
        'status' => 'required|in:success,failed',
        'response_body' => 'nullable|array',
        'error_message' => 'nullable|string',
        'execution_time_ms' => 'integer|min:0',
    ];

    // ============================================
    // Query Scopes
    // ============================================

    /**
     * Scope to filter by type.
     *
     * @param Builder $query
     * @param string $type
     * @return Builder
     */
    public function scopeOfType(Builder $query, string $type): Builder
    {
        return $query->where('type', $type);
    }

    /**
     * Scope to get SMTP send logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeSmtpSends(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_SMTP_SEND);
    }

    /**
     * Scope to get IMAP receive logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeImapReceives(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_IMAP_RECEIVE);
    }

    /**
     * Scope to get test logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeTests(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_TEST);
    }

    /**
     * Scope to filter by status.
     *
     * @param Builder $query
     * @param string $status
     * @return Builder
     */
    public function scopeWithStatus(Builder $query, string $status): Builder
    {
        return $query->where('status', $status);
    }

    /**
     * Scope to get successful logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeSuccessful(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_SUCCESS);
    }

    /**
     * Scope to get failed logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeFailed(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_FAILED);
    }

    /**
     * Scope to filter by recipient email.
     *
     * @param Builder $query
     * @param string $email
     * @return Builder
     */
    public function scopeToRecipient(Builder $query, string $email): Builder
    {
        return $query->where('recipient', $email);
    }

    /**
     * Scope to filter by date range.
     *
     * @param Builder $query
     * @param \Illuminate\Support\Carbon $startDate
     * @param \Illuminate\Support\Carbon $endDate
     * @return Builder
     */
    public function scopeDateRange(Builder $query, $startDate, $endDate): Builder
    {
        return $query->whereBetween('created_at', [$startDate, $endDate]);
    }

    /**
     * Scope to get recent logs (last N hours).
     *
     * @param Builder $query
     * @param int $hours
     * @return Builder
     */
    public function scopeRecent(Builder $query, int $hours = 24): Builder
    {
        return $query->where('created_at', '>=', now()->subHours($hours));
    }

    /**
     * Scope to get today's logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeToday(Builder $query): Builder
    {
        return $query->whereDate('created_at', today());
    }

    /**
     * Scope to get this week's logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeThisWeek(Builder $query): Builder
    {
        return $query->whereBetween('created_at', [
            now()->startOfWeek(),
            now()->endOfWeek()
        ]);
    }

    /**
     * Scope to get this month's logs.
     *
     * @param Builder $query
     * @return Builder
     */
    public function scopeThisMonth(Builder $query): Builder
    {
        return $query->whereBetween('created_at', [
            now()->startOfMonth(),
            now()->endOfMonth()
        ]);
    }

    // ============================================
    // Static Factory Methods
    // ============================================

    /**
     * Create a log entry for SMTP send.
     *
     * @param string $recipient
     * @param string $subject
     * @param bool $success
     * @param array|null $response
     * @param string|null $errorMessage
     * @param int $executionTimeMs
     * @return self
     */
    public static function logSmtpSend(
        string $recipient,
        string $subject,
        bool $success,
        ?array $response = null,
        ?string $errorMessage = null,
        int $executionTimeMs = 0
    ): self {
        return self::create([
            'type' => self::TYPE_SMTP_SEND,
            'recipient' => $recipient,
            'subject' => $subject,
            'status' => $success ? self::STATUS_SUCCESS : self::STATUS_FAILED,
            'response_body' => $response,
            'error_message' => $errorMessage,
            'execution_time_ms' => $executionTimeMs,
            'created_at' => now(),
        ]);
    }

    /**
     * Create a log entry for IMAP receive.
     *
     * @param bool $success
     * @param array|null $response
     * @param string|null $errorMessage
     * @param int $executionTimeMs
     * @return self
     */
    public static function logImapReceive(
        bool $success,
        ?array $response = null,
        ?string $errorMessage = null,
        int $executionTimeMs = 0
    ): self {
        return self::create([
            'type' => self::TYPE_IMAP_RECEIVE,
            'status' => $success ? self::STATUS_SUCCESS : self::STATUS_FAILED,
            'response_body' => $response,
            'error_message' => $errorMessage,
            'execution_time_ms' => $executionTimeMs,
            'created_at' => now(),
        ]);
    }

    /**
     * Create a log entry for connection test.
     *
     * @param string $type 'smtp' or 'imap'
     * @param bool $success
     * @param array|null $response
     * @param string|null $errorMessage
     * @param int $executionTimeMs
     * @return self
     */
    public static function logTest(
        string $type,
        bool $success,
        ?array $response = null,
        ?string $errorMessage = null,
        int $executionTimeMs = 0
    ): self {
        return self::create([
            'type' => self::TYPE_TEST,
            'subject' => "{$type} connection test",
            'status' => $success ? self::STATUS_SUCCESS : self::STATUS_FAILED,
            'response_body' => $response,
            'error_message' => $errorMessage,
            'execution_time_ms' => $executionTimeMs,
            'created_at' => now(),
        ]);
    }

    // ============================================
    // Accessors
    // ============================================

    /**
     * Get the type label for display.
     *
     * @return string
     */
    public function getTypeLabelAttribute(): string
    {
        return match($this->type) {
            self::TYPE_SMTP_SEND => 'SMTP Send',
            self::TYPE_IMAP_RECEIVE => 'IMAP Receive',
            self::TYPE_TEST => 'Connection Test',
            default => ucfirst($this->type),
        };
    }

    /**
     * Get the status badge CSS class.
     *
     * @return string
     */
    public function getStatusBadgeAttribute(): string
    {
        return $this->status === self::STATUS_SUCCESS
            ? 'bg-green-100 text-green-800'
            : 'bg-red-100 text-red-800';
    }

    /**
     * Get formatted execution time.
     *
     * @return string
     */
    public function getFormattedExecutionTimeAttribute(): string
    {
        if ($this->execution_time_ms >= 1000) {
            return round($this->execution_time_ms / 1000, 2) . 's';
        }
        return $this->execution_time_ms . 'ms';
    }

    /**
     * Get time ago string.
     *
     * @return string
     */
    public function getTimeAgoAttribute(): string
    {
        return $this->created_at->diffForHumans();
    }

    // ============================================
    // Statistics Methods
    // ============================================

    /**
     * Get log statistics summary.
     *
     * @return array
     */
    public static function getStatistics(): array
    {
        $total = self::count();
        $successful = self::successful()->count();
        $failed = self::failed()->count();

        return [
            'total' => $total,
            'successful' => $successful,
            'failed' => $failed,
            'success_rate' => $total > 0 ? round(($successful / $total) * 100, 1) : 0,
            'today' => self::today()->count(),
            'this_week' => self::thisWeek()->count(),
            'this_month' => self::thisMonth()->count(),
            'avg_execution_time' => self::avg('execution_time_ms') ?? 0,
        ];
    }

    /**
     * Get recent activity summary.
     *
     * @param int $hours
     * @return array
     */
    public static function getRecentActivity(int $hours = 24): array
    {
        $recent = self::recent($hours);

        return [
            'total' => $recent->count(),
            'smtp_sends' => (clone $recent)->smtpSends()->count(),
            'imap_receives' => (clone $recent)->imapReceives()->count(),
            'tests' => (clone $recent)->tests()->count(),
            'successful' => (clone $recent)->successful()->count(),
            'failed' => (clone $recent)->failed()->count(),
        ];
    }
}
