<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Str;

class Allegato extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'allegati';

    protected $fillable = [
        'codice_allegato',
        'stabile_id',
        'nome_file_originale',
        'nome_file_storage',
        'percorso_file_storage',
        'tipo_mime',
        'dimensione_byte',
        'descrizione',
        'allegabile_id',
        'allegabile_type',
        'user_id',
        'tags',
    ];

    protected $casts = [
        'dimensione_byte' => 'integer',
        'tags' => 'array',
    ];

    /**
     * Boot del modello per generare automaticamente il codice allegato.
     */
    protected static function boot()
    {
        parent::boot();
        
        static::creating(function ($allegato) {
            if (empty($allegato->codice_allegato)) {
                $allegato->codice_allegato = static::generateCodiceAllegato();
            }
        });
    }

    /**
     * Genera un codice alfanumerico univoco di 8 caratteri per l'allegato.
     */
    private static function generateCodiceAllegato(): string
    {
        do {
            $codice = 'A' . strtoupper(Str::random(7)); // A + 7 caratteri casuali
        } while (static::where('codice_allegato', $codice)->exists());
        
        return $codice;
    }

    /**
     * Relazione morphable con l'entità a cui è allegato il file.
     */
    public function allegabile(): MorphTo
    {
        return $this->morphTo();
    }

    /**
     * Relazione con lo stabile.
     */
    public function stabile(): BelongsTo
    {
        return $this->belongsTo(Stabile::class);
    }

    /**
     * Relazione con l'utente che ha caricato il file.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Ottiene la dimensione del file in formato leggibile.
     */
    public function getDimensioneLeggibileAttribute(): string
    {
        $bytes = $this->dimensione_byte;
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, 2) . ' ' . $units[$i];
    }

    /**
     * Verifica se il file è un'immagine.
     */
    public function isImmagine(): bool
    {
        return strpos($this->tipo_mime, 'image/') === 0;
    }

    /**
     * Verifica se il file è un PDF.
     */
    public function isPdf(): bool
    {
        return $this->tipo_mime === 'application/pdf';
    }

    /**
     * Verifica se il file è un documento Office.
     */
    public function isDocumentoOffice(): bool
    {
        $tipiOffice = [
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/vnd.ms-powerpoint',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        ];
        
        return in_array($this->tipo_mime, $tipiOffice);
    }

    /**
     * Ottiene l'URL per il download del file.
     */
    public function getUrlDownload(): string
    {
        return route('allegati.download', $this->codice_allegato);
    }

    /**
     * Scope per filtrare per tipo di entità allegabile.
     */
    public function scopeForEntity($query, string $entityType, int $entityId)
    {
        return $query->where('allegabile_type', $entityType)
                    ->where('allegabile_id', $entityId);
    }

    /**
     * Scope per filtrare per stabile.
     */
    public function scopeForStabile($query, int $stabileId)
    {
        return $query->where('stabile_id', $stabileId);
    }

    /**
     * Scope per filtrare per tipo MIME.
     */
    public function scopeByMimeType($query, string $mimeType)
    {
        return $query->where('tipo_mime', 'like', $mimeType . '%');
    }
}
