<?php

namespace App\Models;

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

class PendingSyncQueue extends Model
{
    use HasFactory;

    protected $table = 'pending_sync_queue';

    protected $fillable = [
        'dns_zone_id',
        'nameserver_id',
        'action',
        'dns_record_id',
        'payload',
        'retry_count',
        'max_retries',
        'last_attempt_at',
        'last_error',
        'status',
        'priority',
    ];

    protected $casts = [
        'payload' => 'array',
        'last_attempt_at' => 'datetime',
    ];

    // Status constants
    const STATUS_PENDING = 'pending';
    const STATUS_PROCESSING = 'processing';
    const STATUS_FAILED = 'failed';
    const STATUS_COMPLETED = 'completed';

    // Action constants
    const ACTION_CREATE = 'create';
    const ACTION_UPDATE = 'update';
    const ACTION_DELETE = 'delete';
    const ACTION_FULL_SYNC = 'full_sync';

    // Priority constants
    const PRIORITY_LOW = 'low';
    const PRIORITY_NORMAL = 'normal';
    const PRIORITY_HIGH = 'high';

    /**
     * Relație cu zona DNS
     */
    public function dnsZone()
    {
        return $this->belongsTo(DnsZone::class, 'dns_zone_id');
    }

    /**
     * Relație cu nameserver-ul
     */
    public function nameserver()
    {
        return $this->belongsTo(NameServer::class, 'nameserver_id');
    }

    /**
     * Relație cu record-ul DNS (opțional)
     */
    public function dnsRecord()
    {
        return $this->belongsTo(DnsRecord::class, 'dns_record_id');
    }

    /**
     * Scope pentru elemente pending
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Scope pentru elemente failed care pot fi reîncercate
     */
    public function scopeRetryable($query)
    {
        return $query->where('status', self::STATUS_FAILED)
                     ->whereColumn('retry_count', '<', 'max_retries');
    }

    /**
     * Scope pentru un nameserver specific
     */
    public function scopeForNameserver($query, $nameserverId)
    {
        return $query->where('nameserver_id', $nameserverId);
    }

    /**
     * Scope pentru o zonă specifică
     */
    public function scopeForZone($query, $zoneId)
    {
        return $query->where('dns_zone_id', $zoneId);
    }

    /**
     * Scope ordonat după prioritate
     */
    public function scopeOrderByPriority($query)
    {
        return $query->orderByRaw("FIELD(priority, 'high', 'normal', 'low')");
    }

    /**
     * Verifică dacă poate fi reîncercat
     */
    public function canRetry(): bool
    {
        return $this->retry_count < $this->max_retries;
    }

    /**
     * Marchează ca procesare în curs
     */
    public function markAsProcessing(): void
    {
        $this->update([
            'status' => self::STATUS_PROCESSING,
            'last_attempt_at' => now(),
        ]);
    }

    /**
     * Marchează ca completat cu succes
     */
    public function markAsCompleted(): void
    {
        $this->update([
            'status' => self::STATUS_COMPLETED,
            'last_error' => null,
        ]);
    }

    /**
     * Marchează ca eșuat
     */
    public function markAsFailed(string $error): void
    {
        $this->increment('retry_count');

        $newStatus = $this->canRetry() ? self::STATUS_PENDING : self::STATUS_FAILED;

        $this->update([
            'status' => $newStatus,
            'last_error' => $error,
            'last_attempt_at' => now(),
        ]);
    }

    /**
     * Adaugă un element în coadă (sau actualizează dacă există deja)
     */
    public static function queueSync(
        int $zoneId,
        int $nameserverId,
        string $action = self::ACTION_FULL_SYNC,
        ?int $recordId = null,
        ?array $payload = null,
        string $priority = self::PRIORITY_NORMAL
    ): self {
        // Verifică dacă există deja un element pending pentru aceeași combinație
        $existing = self::where('dns_zone_id', $zoneId)
            ->where('nameserver_id', $nameserverId)
            ->where('action', $action)
            ->where('dns_record_id', $recordId)
            ->whereIn('status', [self::STATUS_PENDING, self::STATUS_PROCESSING])
            ->first();

        if ($existing) {
            // Actualizează prioritatea dacă noua este mai mare
            if ($priority === self::PRIORITY_HIGH && $existing->priority !== self::PRIORITY_HIGH) {
                $existing->update(['priority' => $priority]);
            }
            return $existing;
        }

        return self::create([
            'dns_zone_id' => $zoneId,
            'nameserver_id' => $nameserverId,
            'action' => $action,
            'dns_record_id' => $recordId,
            'payload' => $payload,
            'priority' => $priority,
            'status' => self::STATUS_PENDING,
        ]);
    }

    /**
     * Curăță elementele vechi completate
     */
    public static function cleanupCompleted(int $daysOld = 7): int
    {
        return self::where('status', self::STATUS_COMPLETED)
            ->where('updated_at', '<', now()->subDays($daysOld))
            ->delete();
    }
}
