<?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\SoftDeletes;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;

class Attachment extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'ticket_id',
        'response_id',
        'user_id',
        'filename',
        'original_filename',
        'mime_type',
        'size',
        'storage_path',
        'storage_disk',
        'virus_scanned',
        'virus_detected',
        'virus_scan_result',
        'is_inline',
        'is_from_email',
        'thumbnail_path',
        'download_count',
    ];

    protected $casts = [
        'virus_scanned' => 'boolean',
        'virus_detected' => 'boolean',
        'is_inline' => 'boolean',
        'is_from_email' => 'boolean',
        'download_count' => 'integer',
        'size' => 'integer',
    ];

    /**
     * Get the ticket that owns this attachment.
     */
    public function ticket(): BelongsTo
    {
        return $this->belongsTo(Tickets::class, 'ticket_id');
    }

    /**
     * Get the response that owns this attachment (if any).
     */
    public function response(): BelongsTo
    {
        return $this->belongsTo(Responses::class, 'response_id');
    }

    /**
     * Get the user who uploaded this attachment.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * Get human-readable file size.
     */
    public function getFormattedSizeAttribute(): string
    {
        $bytes = $this->size;
        $units = ['B', 'KB', 'MB', 'GB'];

        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }

        return round($bytes, 2) . ' ' . $units[$i];
    }

    /**
     * Get file extension from original filename.
     */
    public function getExtensionAttribute(): string
    {
        return strtolower(pathinfo($this->original_filename, PATHINFO_EXTENSION));
    }

    /**
     * Check if attachment is an image.
     */
    public function isImage(): bool
    {
        return str_starts_with($this->mime_type, 'image/');
    }

    /**
     * Check if attachment is a video.
     */
    public function isVideo(): bool
    {
        return str_starts_with($this->mime_type, 'video/');
    }

    /**
     * Check if attachment is a PDF.
     */
    public function isPdf(): bool
    {
        return $this->mime_type === 'application/pdf';
    }

    /**
     * Check if attachment is safe to download (no virus detected).
     */
    public function isSafe(): bool
    {
        return !$this->virus_detected;
    }

    /**
     * Check if attachment needs virus scanning.
     */
    public function needsVirusScan(): bool
    {
        return !$this->virus_scanned;
    }

    /**
     * Generate a signed URL for downloading this attachment.
     *
     * @param int $expiresInMinutes
     * @return string
     */
    public function getSignedDownloadUrl(int $expiresInMinutes = 60): string
    {
        return URL::temporarySignedRoute(
            'attachments.download',
            now()->addMinutes($expiresInMinutes),
            ['attachment' => $this->id]
        );
    }

    /**
     * Get the full storage path for the file.
     */
    public function getFullStoragePath(): string
    {
        return Storage::disk($this->storage_disk)->path($this->storage_path);
    }

    /**
     * Check if the file exists in storage.
     */
    public function fileExists(): bool
    {
        return Storage::disk($this->storage_disk)->exists($this->storage_path);
    }

    /**
     * Get the thumbnail URL if available.
     */
    public function getThumbnailUrl(): ?string
    {
        if (!$this->thumbnail_path) {
            return null;
        }

        if ($this->storage_disk === 'public') {
            return Storage::disk($this->storage_disk)->url($this->thumbnail_path);
        }

        // For private disks, return signed URL
        return URL::temporarySignedRoute(
            'attachments.thumbnail',
            now()->addHours(24),
            ['attachment' => $this->id]
        );
    }

    /**
     * Increment download counter.
     */
    public function incrementDownloadCount(): void
    {
        $this->increment('download_count');
    }

    /**
     * Scope to get only safe attachments (no virus detected).
     */
    public function scopeSafe($query)
    {
        return $query->where('virus_detected', false);
    }

    /**
     * Scope to get only scanned attachments.
     */
    public function scopeScanned($query)
    {
        return $query->where('virus_scanned', true);
    }

    /**
     * Scope to get attachments pending virus scan.
     */
    public function scopePendingScan($query)
    {
        return $query->where('virus_scanned', false);
    }

    /**
     * Scope to get only images.
     */
    public function scopeImages($query)
    {
        return $query->where('mime_type', 'like', 'image/%');
    }

    /**
     * Delete the physical file when model is deleted.
     */
    protected static function booted(): void
    {
        static::deleted(function (Attachment $attachment) {
            // Delete main file
            if ($attachment->fileExists()) {
                Storage::disk($attachment->storage_disk)->delete($attachment->storage_path);
            }

            // Delete thumbnail if exists
            if ($attachment->thumbnail_path) {
                Storage::disk($attachment->storage_disk)->delete($attachment->thumbnail_path);
            }

            // Update user storage quota
            if ($attachment->user) {
                $attachment->user->decrement('storage_used_bytes', $attachment->size);
            }
        });
    }
}
