<?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\Facades\Storage;

/**
 * Model: RPublicationFile (Research Publication File)
 * 
 * Represents file attachments for research publications.
 * Supports version control and secure file handling.
 * 
 * @property int $id
 * @property int $publication_id
 * @property string $original_name
 * @property string $stored_name
 * @property string $file_path
 * @property int $file_size
 * @property string $mime_type
 * @property string $file_type
 * @property bool $is_public
 * @property int $version
 * @property int|null $replaces_file_id
 * @property string|null $description
 */
class RPublicationFile extends Model
{
    use HasFactory;

    protected $table = 'r_publication_files';

    protected $fillable = [
        'publication_id',
        'original_name',
        'stored_name',
        'file_path',
        'file_size',
        'mime_type',
        'file_type',
        'is_public',
        'version',
        'replaces_file_id',
        'description',
        'download_count',
    ];

    protected $casts = [
        'is_public'      => 'boolean',
        'file_size'      => 'integer',
        'version'        => 'integer',
        'download_count' => 'integer',
    ];

    /**
     * File type constants.
     */
    const TYPE_PDF = 'pdf';
    const TYPE_DOC = 'doc';
    const TYPE_DOCX = 'docx';
    const TYPE_IMAGE = 'image';
    const TYPE_OTHER = 'other';

    /**
     * Get the publication this file belongs to.
     */
    public function publication(): BelongsTo
    {
        return $this->belongsTo(RPublication::class, 'publication_id');
    }

    /**
     * Get the previous version of this file.
     */
    public function previousVersion(): BelongsTo
    {
        return $this->belongsTo(self::class, 'replaces_file_id');
    }

    /**
     * Get newer versions of this file.
     */
    public function newerVersions(): HasMany
    {
        return $this->hasMany(self::class, 'replaces_file_id');
    }

    /**
     * Get the full URL to the file.
     */
    public function getUrlAttribute(): string
    {
        if ($this->is_public) {
            return Storage::url($this->file_path);
        }
        
        return route('research.files.download', $this->id);
    }

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

        while ($bytes >= 1024 && $unitIndex < count($units) - 1) {
            $bytes /= 1024;
            $unitIndex++;
        }

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

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

    /**
     * Check if file is an image.
     */
    public function isImage(): bool
    {
        return $this->file_type === self::TYPE_IMAGE || 
               str_starts_with($this->mime_type, 'image/');
    }

    /**
     * Check if file can be previewed.
     */
    public function canPreview(): bool
    {
        return $this->isPdf() || $this->isImage();
    }

    /**
     * Get the file icon based on type.
     */
    public function getIconAttribute(): string
    {
        return match($this->file_type) {
            self::TYPE_PDF => 'fa-file-pdf',
            self::TYPE_DOC, self::TYPE_DOCX => 'fa-file-word',
            self::TYPE_IMAGE => 'fa-file-image',
            default => 'fa-file',
        };
    }
}
