<?php

namespace App\Models\Commons;

use App\Models\FileShareLink;
use App\Models\Folder;
use App\Models\Members\User;
use App\Models\Tenants\Tenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;

/**
 * @mixin IdeHelperFile
 */
class File extends Model
{
    use \App\Traits\BelongsToTenant;
    use \App\Traits\ModelTrait;
    use SoftDeletes;

    protected $table = 'files';

    protected $fillable = [
        'tenant_id',
        'file_path',
        // Old fields (legacy support)
        'original_name',
        'file_name',
        'file_name_old',
        'fileable_id',
        'fileable_type',
        // New fields
        'display_name',
        'stored_name',
        'folder_id',
        'is_temp',
        'file_type',
        'field_key',
        'document_id',
        'document_type',
        'file_size',
        'mime_type',
        'description',
        'uploaded_by',
        'deleted_by',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'is_temp' => 'boolean',
        'file_size' => 'integer',
        'deleted_at' => 'datetime',
    ];

    /**
     * Get the tenant that owns the file
     */
    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    /**
     * Get the folder that contains this file
     */
    public function folder(): BelongsTo
    {
        return $this->belongsTo(Folder::class);
    }

    /**
     * Get all share links for this file
     */
    public function shareLinks(): HasMany
    {
        return $this->hasMany(FileShareLink::class);
    }

    /**
     * Get the uploader (User)
     */
    public function uploader(): BelongsTo
    {
        return $this->belongsTo(User::class, 'uploaded_by');
    }

    /**
     * Legacy: 연관된 모델 (Polymorphic) - for backward compatibility
     *
     * @deprecated Use document_id and document_type instead
     */
    public function fileable()
    {
        return $this->morphTo();
    }

    /**
     * Get the full storage path
     */
    public function getStoragePath(): string
    {
        return Storage::disk('tenant')->path($this->file_path);
    }

    /**
     * Check if file exists in storage
     */
    public function exists(): bool
    {
        return Storage::disk('tenant')->exists($this->file_path);
    }

    /**
     * Get download response
     */
    public function download()
    {
        if (! $this->exists()) {
            abort(404, 'File not found in storage');
        }

        return response()->download(
            $this->getStoragePath(),
            $this->display_name ?? $this->original_name
        );
    }

    /**
     * Move file from temp to folder
     */
    public function moveToFolder(Folder $folder): bool
    {
        if (! $this->is_temp) {
            return false; // Already moved
        }

        // New path: /tenants/{tenant_id}/{folder_key}/{year}/{month}/{stored_name}
        $date = now();
        $newPath = sprintf(
            '%d/%s/%s/%s/%s',
            $this->tenant_id,
            $folder->folder_key,
            $date->format('Y'),
            $date->format('m'),
            $this->stored_name ?? $this->file_name
        );

        // Move physical file
        if (Storage::disk('tenant')->exists($this->file_path)) {
            Storage::disk('tenant')->move($this->file_path, $newPath);
        }

        // Update DB
        $this->update([
            'file_path' => $newPath,
            'folder_id' => $folder->id,
            'is_temp' => false,
        ]);

        return true;
    }

    /**
     * Delete file (soft delete)
     */
    public function softDeleteFile(int $userId): void
    {
        // Set deleted_by before soft delete
        $this->deleted_by = $userId;
        $this->save();

        // Use SoftDeletes trait's delete() method
        $this->delete();
    }

    /**
     * Permanently delete file
     */
    public function permanentDelete(): void
    {
        // Delete physical file
        if ($this->exists()) {
            Storage::disk('tenant')->delete($this->file_path);
        }

        // Decrement tenant storage
        $tenant = Tenant::find($this->tenant_id);
        if ($tenant) {
            $tenant->decrement('storage_used', $this->file_size);
        }

        // Force delete from DB
        $this->forceDelete();
    }

    /**
     * Scope: Temp files only
     */
    public function scopeTemp($query)
    {
        return $query->where('is_temp', true);
    }

    /**
     * Scope: Non-temp files only
     */
    public function scopeNonTemp($query)
    {
        return $query->where('is_temp', false);
    }

    /**
     * Scope: By folder
     */
    public function scopeInFolder($query, $folderId)
    {
        return $query->where('folder_id', $folderId);
    }

    /**
     * Scope: By document
     */
    public function scopeForDocument($query, int $documentId, string $documentType)
    {
        return $query->where('document_id', $documentId)
            ->where('document_type', $documentType);
    }
}
