<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;

class BroadcastCampaign extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'message',
        'attachments',
        'inline_keyboard',
        'status',
        'scheduled_at',
        'started_at',
        'completed_at',
        'total_recipients',
        'sent_count',
        'failed_count',
        'target_filters',
        'settings',
        'created_by',
    ];

    protected $casts = [
        'attachments' => 'array',
        'inline_keyboard' => 'array',
        'target_filters' => 'array',
        'settings' => 'array',
        'scheduled_at' => 'datetime',
        'started_at' => 'datetime',
        'completed_at' => 'datetime',
    ];

    // Status constants
    public const STATUS_DRAFT = 'draft';
    public const STATUS_SCHEDULED = 'scheduled';
    public const STATUS_SENDING = 'sending';
    public const STATUS_SENT = 'sent';
    public const STATUS_PAUSED = 'paused';
    public const STATUS_CANCELLED = 'cancelled';

    /**
     * Get the user who created this campaign
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get all recipients for this campaign
     */
    public function recipients(): HasMany
    {
        return $this->hasMany(BroadcastRecipient::class, 'campaign_id');
    }

    /**
     * Get successful recipients
     */
    public function sentRecipients(): HasMany
    {
        return $this->hasMany(BroadcastRecipient::class, 'campaign_id')
                   ->where('status', BroadcastRecipient::STATUS_SENT);
    }

    /**
     * Get failed recipients
     */
    public function failedRecipients(): HasMany
    {
        return $this->hasMany(BroadcastRecipient::class, 'campaign_id')
                   ->where('status', BroadcastRecipient::STATUS_FAILED);
    }

    /**
     * Scope for active campaigns
     */
    public function scopeActive($query)
    {
        return $query->whereNotIn('status', [self::STATUS_CANCELLED]);
    }

    /**
     * Scope for completed campaigns
     */
    public function scopeCompleted($query)
    {
        return $query->where('status', self::STATUS_SENT);
    }

    /**
     * Scope for scheduled campaigns
     */
    public function scopeScheduled($query)
    {
        return $query->where('status', self::STATUS_SCHEDULED);
    }

    /**
     * Scope for ready to send campaigns
     */
    public function scopeReadyToSend($query)
    {
        return $query->where('status', self::STATUS_SCHEDULED)
                    ->where('scheduled_at', '<=', now());
    }

    /**
     * Check if campaign is editable
     */
    public function isEditable(): bool
    {
        return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_PAUSED]);
    }

    /**
     * Check if campaign is in progress
     */
    public function isInProgress(): bool
    {
        return $this->status === self::STATUS_SENDING;
    }

    /**
     * Check if campaign is completed
     */
    public function isCompleted(): bool
    {
        return in_array($this->status, [self::STATUS_SENT, self::STATUS_CANCELLED]);
    }

    /**
     * Get progress percentage
     */
    public function getProgressAttribute(): float
    {
        if ($this->total_recipients === 0) {
            return 0;
        }

        return round(($this->sent_count + $this->failed_count) / $this->total_recipients * 100, 2);
    }

    /**
     * Get success rate percentage
     */
    public function getSuccessRateAttribute(): float
    {
        $processed = $this->sent_count + $this->failed_count;
        
        if ($processed === 0) {
            return 0;
        }

        return round($this->sent_count / $processed * 100, 2);
    }

    /**
     * Get estimated completion time
     */
    public function getEstimatedCompletionAttribute(): ?Carbon
    {
        if (!$this->isInProgress() || $this->sent_count === 0) {
            return null;
        }

        $elapsed = $this->started_at->diffInSeconds(now());
        $rate = $this->sent_count / $elapsed; // messages per second
        $remaining = $this->total_recipients - ($this->sent_count + $this->failed_count);

        if ($rate <= 0) {
            return null;
        }

        return now()->addSeconds($remaining / $rate);
    }

    /**
     * Start the campaign
     */
    public function start(): bool
    {
        if (!in_array($this->status, [self::STATUS_DRAFT, self::STATUS_SCHEDULED, self::STATUS_PAUSED])) {
            return false;
        }

        $this->update([
            'status' => self::STATUS_SENDING,
            'started_at' => now(),
        ]);

        return true;
    }

    /**
     * Pause the campaign
     */
    public function pause(): bool
    {
        if ($this->status !== self::STATUS_SENDING) {
            return false;
        }

        $this->update(['status' => self::STATUS_PAUSED]);
        return true;
    }

    /**
     * Cancel the campaign
     */
    public function cancel(): bool
    {
        if ($this->isCompleted()) {
            return false;
        }

        $this->update([
            'status' => self::STATUS_CANCELLED,
            'completed_at' => now(),
        ]);

        return true;
    }

    /**
     * Mark campaign as completed
     */
    public function complete(): bool
    {
        if ($this->status !== self::STATUS_SENDING) {
            return false;
        }

        $this->update([
            'status' => self::STATUS_SENT,
            'completed_at' => now(),
        ]);

        return true;
    }
}