<?php

namespace App\Models\Disk;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Storage;

class DiskItem extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * The table associated with the model.
     */
    protected $table = 'disk_items';

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'folder_id',
        'title',
        'description',
        'alt_text',
        'tags',
        'original_name',
        'filename',
        'file_path',
        'file_url',
        'mime_type',
        'extension',
        'file_size',
        'file_type',
        'file_hash',
        'width',
        'height',
        'aspect_ratio',
        'orientation',
        'thumbnails',
        'thumbnail_path',
        'has_webp',
        'preview_type',
        'is_processed',
        'processing_data',
        'dominant_color',
        'color_palette',
        'page_count',
        'word_count',
        'language',
        'extracted_text',
        'usage_references',
        'usage_count',
        'is_featured',
        'sort_order',
        'quality',
        'metadata',
        'parent_version_id',
        'version_number',
        'is_latest_version',
        'version_notes',
        'copyright',
        'author',
        'source',
        'created_date',
        'location_data',
        'is_active',
        'is_public',
        'is_approved',
        'approved_at',
        'approved_by',
        'is_optimized',
        'original_size',
        'compression_ratio',
        'view_count',
        'download_count',
        'last_viewed_at',
        'last_downloaded_at',
        'created_by',
        'updated_by',
    ];

    /**
     * The attributes that should be cast.
     */
    protected function casts(): array
    {
        return [
            'tags' => 'array',
            'thumbnails' => 'array',
            'processing_data' => 'array',
            'color_palette' => 'array',
            'usage_references' => 'array',
            'metadata' => 'array',
            'location_data' => 'array',
            'file_size' => 'integer',
            'width' => 'integer',
            'height' => 'integer',
            'aspect_ratio' => 'decimal:3',
            'page_count' => 'integer',
            'word_count' => 'integer',
            'usage_count' => 'integer',
            'sort_order' => 'integer',
            'version_number' => 'integer',
            'original_size' => 'integer',
            'compression_ratio' => 'decimal:2',
            'view_count' => 'integer',
            'download_count' => 'integer',
            'has_webp' => 'boolean',
            'is_processed' => 'boolean',
            'is_featured' => 'boolean',
            'is_latest_version' => 'boolean',
            'is_active' => 'boolean',
            'is_public' => 'boolean',
            'is_approved' => 'boolean',
            'is_optimized' => 'boolean',
            'approved_at' => 'datetime',
            'created_date' => 'datetime',
            'last_viewed_at' => 'datetime',
            'last_downloaded_at' => 'datetime',
            'created_at' => 'datetime',
            'updated_at' => 'datetime',
            'deleted_at' => 'datetime',
        ];
    }

    /**
     * Get the folder that owns this item.
     */
    public function folder(): BelongsTo
    {
        return $this->belongsTo(DiskFolder::class, 'folder_id');
    }

    /**
     * Get the parent version of this item.
     */
    public function parentVersion(): BelongsTo
    {
        return $this->belongsTo(DiskItem::class, 'parent_version_id');
    }

    /**
     * Get all versions of this item.
     */
    public function versions(): HasMany
    {
        return $this->hasMany(DiskItem::class, 'parent_version_id')
            ->orderBy('version_number', 'desc');
    }

    /**
     * Get the user who approved this item.
     */
    public function approver(): BelongsTo
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

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

    /**
     * Get the user who last updated this item.
     */
    public function updater(): BelongsTo
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

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

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

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

    /**
     * Get file type icon class.
     */
    public function getFileIconAttribute(): string
    {
        // Check for PDF specifically
        if ($this->extension === 'pdf') {
            return 'fa-file-pdf';
        }

        // Check for Word documents
        if (in_array($this->extension, ['doc', 'docx'])) {
            return 'fa-file-word';
        }

        return match ($this->file_type) {
            'image' => 'fa-file-image',
            'document' => 'fa-file-alt',
            'video' => 'fa-file-video',
            'audio' => 'fa-file-audio',
            'archive' => 'fa-file-archive',
            'spreadsheet' => 'fa-file-excel',
            'presentation' => 'fa-file-powerpoint',
            default => 'fa-file',
        };
    }

    /**
     * Get file type color.
     */
    public function getFileColorAttribute(): string
    {
        // PDF gets special red color
        if ($this->extension === 'pdf') {
            return '#dc2626'; // red-600
        }

        // Word documents get blue
        if (in_array($this->extension, ['doc', 'docx'])) {
            return '#2563eb'; // blue-600
        }

        return match ($this->file_type) {
            'image' => '#22c55e', // green
            'document' => '#3b82f6', // blue
            'video' => '#ef4444', // red
            'audio' => '#8b5cf6', // purple
            'archive' => '#f59e0b', // amber
            'spreadsheet' => '#10b981', // emerald
            'presentation' => '#f97316', // orange
            default => '#6b7280', // gray
        };
    }

    /**
     * Check if item is an image.
     */
    public function isImage(): bool
    {
        return $this->file_type === 'image';
    }

    /**
     * Check if item is a document.
     */
    public function isDocument(): bool
    {
        return in_array($this->file_type, ['document', 'spreadsheet', 'presentation']);
    }

    /**
     * Check if item is a video.
     */
    public function isVideo(): bool
    {
        return $this->file_type === 'video';
    }

    /**
     * Check if item is an audio file.
     */
    public function isAudio(): bool
    {
        return $this->file_type === 'audio';
    }

    /**
     * Check if item is an archive.
     */
    public function isArchive(): bool
    {
        return $this->file_type === 'archive';
    }

    /**
     * Check if item has a preview available.
     */
    public function hasPreview(): bool
    {
        return !empty($this->thumbnail_path) || !empty($this->preview_type);
    }

    /**
     * Check if item has versions.
     */
    public function hasVersions(): bool
    {
        return $this->versions()->count() > 0;
    }

    /**
     * Get the latest version of this item.
     */
    public function getLatestVersion(): ?self
    {
        return $this->versions()
            ->where('is_latest_version', true)
            ->first();
    }

    /**
     * Get full file URL.
     */
    public function getFullUrlAttribute(): string
    {
        if ($this->file_url) {
            return $this->file_url;
        }

        return Storage::url($this->file_path);
    }

    /**
     * Get thumbnail URL.
     */
    public function getThumbnailUrlAttribute(): string
    {
        // If has actual thumbnail, return it
        if ($this->thumbnail_path) {
            return Storage::url($this->thumbnail_path);
        }

        // Return default icon based on file type
        return $this->getDefaultThumbnail();
    }

    /**
     * Get default thumbnail for non-image files.
     */
    public function getDefaultThumbnail(): string
    {
        $color = $this->file_color;
        $extension = strtoupper($this->extension);

        // Create a simple, beautiful SVG thumbnail
        $svg = <<<SVG
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
    <!-- Background -->
    <rect width="300" height="300" fill="{$color}" opacity="0.08"/>

    <!-- File icon shape -->
    <g transform="translate(75, 50)">
        <path d="M 0,0 L 120,0 L 150,30 L 150,200 L 0,200 Z" fill="{$color}" opacity="0.15"/>
        <path d="M 120,0 L 120,30 L 150,30" fill="{$color}" opacity="0.25"/>
        <rect x="20" y="60" width="110" height="8" rx="4" fill="{$color}" opacity="0.3"/>
        <rect x="20" y="80" width="90" height="8" rx="4" fill="{$color}" opacity="0.3"/>
        <rect x="20" y="100" width="100" height="8" rx="4" fill="{$color}" opacity="0.3"/>
    </g>

    <!-- Extension badge -->
    <rect x="75" y="220" width="150" height="50" rx="8" fill="{$color}"/>
    <text x="150" y="252" font-family="Arial, sans-serif" font-size="22" fill="white" text-anchor="middle" font-weight="bold">
        {$extension}
    </text>
</svg>
SVG;

        return 'data:image/svg+xml;base64,' . base64_encode($svg);
    }

    /**
     * Increment view count.
     */
    public function incrementViews(): void
    {
        $this->increment('view_count');
        $this->update(['last_viewed_at' => now()]);
    }

    /**
     * Increment download count.
     */
    public function incrementDownloads(): void
    {
        $this->increment('download_count');
        $this->update(['last_downloaded_at' => now()]);
    }

    /**
     * Create a new version of this item.
     */
    public function createVersion(array $attributes): self
    {
        // Mark current item as not latest
        $this->update(['is_latest_version' => false]);

        // Create new version
        return self::create(array_merge($attributes, [
            'folder_id' => $this->folder_id,
            'parent_version_id' => $this->id,
            'version_number' => $this->version_number + 1,
            'is_latest_version' => true,
        ]));
    }

    /**
     * Determine file type from mime type.
     */
    public static function determineFileType(string $mimeType): string
    {
        return match (true) {
            str_starts_with($mimeType, 'image/') => 'image',
            str_starts_with($mimeType, 'video/') => 'video',
            str_starts_with($mimeType, 'audio/') => 'audio',
            in_array($mimeType, [
                'application/pdf',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'text/plain',
                'application/rtf',
            ]) => 'document',
            in_array($mimeType, [
                'application/vnd.ms-excel',
                'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'text/csv',
            ]) => 'spreadsheet',
            in_array($mimeType, [
                'application/vnd.ms-powerpoint',
                'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            ]) => 'presentation',
            in_array($mimeType, [
                'application/zip',
                'application/x-rar-compressed',
                'application/x-7z-compressed',
                'application/x-tar',
                'application/gzip',
            ]) => 'archive',
            default => 'other',
        };
    }

    /**
     * Scope to filter active items.
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope to filter public items.
     */
    public function scopePublic($query)
    {
        return $query->where('is_public', true);
    }

    /**
     * Scope to filter approved items.
     */
    public function scopeApproved($query)
    {
        return $query->where('is_approved', true);
    }

    /**
     * Scope to filter featured items.
     */
    public function scopeFeatured($query)
    {
        return $query->where('is_featured', true);
    }

    /**
     * Scope to filter by file type.
     */
    public function scopeByFileType($query, $type)
    {
        return $query->where('file_type', $type);
    }

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

    /**
     * Scope to filter documents only.
     */
    public function scopeDocuments($query)
    {
        return $query->whereIn('file_type', ['document', 'spreadsheet', 'presentation']);
    }

    /**
     * Scope to filter videos only.
     */
    public function scopeVideos($query)
    {
        return $query->where('file_type', 'video');
    }

    /**
     * Scope to filter by folder.
     */
    public function scopeByFolder($query, $folderId)
    {
        return $query->where('folder_id', $folderId);
    }

    /**
     * Scope to filter latest versions only.
     */
    public function scopeLatestVersions($query)
    {
        return $query->where('is_latest_version', true);
    }

    /**
     * Scope to search by filename or title.
     */
    public function scopeSearch($query, $search)
    {
        return $query->where(function ($q) use ($search) {
            $q->where('title', 'like', "%{$search}%")
                ->orWhere('original_name', 'like', "%{$search}%")
                ->orWhere('description', 'like', "%{$search}%")
                ->orWhere('tags', 'like', "%{$search}%");
        });
    }

    /**
     * Boot the model.
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($item) {
            if (auth()->check()) {
                $item->created_by = auth()->id();
            }

            // Auto-determine file type if not set
            if (empty($item->file_type) && !empty($item->mime_type)) {
                $item->file_type = self::determineFileType($item->mime_type);
            }

            // Generate file hash if not set
            if (empty($item->file_hash) && !empty($item->file_path)) {
                if (Storage::exists($item->file_path)) {
                    $item->file_hash = hash_file('sha256', Storage::path($item->file_path));
                }
            }

            // Set default version number
            if (empty($item->version_number)) {
                $item->version_number = 1;
            }
        });

        static::updating(function ($item) {
            if (auth()->check()) {
                $item->updated_by = auth()->id();
            }
        });

        static::created(function ($item) {
            // Update folder statistics
            if ($item->folder) {
                $item->folder->updateStatistics();
            }
        });

        static::updated(function ($item) {
            // Update folder statistics if file size changed
            if ($item->isDirty('file_size') && $item->folder) {
                $item->folder->updateStatistics();
            }
        });

        static::deleting(function ($item) {
            // Delete physical file
            if ($item->file_path && Storage::exists($item->file_path)) {
                Storage::delete($item->file_path);
            }

            // Delete thumbnail
            if ($item->thumbnail_path && Storage::exists($item->thumbnail_path)) {
                Storage::delete($item->thumbnail_path);
            }

            // Delete all thumbnails
            if ($item->thumbnails) {
                foreach ($item->thumbnails as $thumbnail) {
                    if (isset($thumbnail['path']) && Storage::exists($thumbnail['path'])) {
                        Storage::delete($thumbnail['path']);
                    }
                }
            }

            // Update folder statistics
            if ($item->folder) {
                $item->folder->updateStatistics();
            }
        });
    }
}
