<?php

namespace App\Services\Resources;

use App\Models\Resources\Resource;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class ResourceFileService
{
    /**
     * Almacena el archivo de un recurso
     *
     * @param Resource $resource
     * @param UploadedFile $file
     * @return string Ruta relativa del archivo guardado
     */
    public function storeFile(Resource $resource, UploadedFile $file): string
    {
        $path = $this->getFileDirectory($resource->id);
        $filename = $this->generateUniqueFilename($file);
        
        $file->storeAs($path, $filename, 'public');
        
        return $this->getRelativePath($resource->id, $filename);
    }

    /**
     * Elimina el archivo de un recurso
     *
     * @param Resource $resource
     * @return bool
     */
    public function deleteFile(Resource $resource): bool
    {
        if (!$resource->path) {
            return false;
        }

        $deleted = Storage::disk('public')->delete($resource->path);

        // Si se eliminó el archivo, intentar eliminar el directorio si está vacío
        $directory = $this->getFileDirectory($resource->id);
        if ($deleted && Storage::disk('public')->exists($directory)) {
            $files = Storage::disk('public')->files($directory);
            if (empty($files)) {
                Storage::disk('public')->deleteDirectory($directory);
            }
        }

        return $deleted;
    }

    /**
     * Elimina todos los archivos de un recurso (incluyendo directorio)
     *
     * @param Resource $resource
     * @return void
     */
    public function deleteAllResourceFiles(Resource $resource): void
    {
        $directory = $this->getFileDirectory($resource->id);
        
        if (Storage::disk('public')->exists($directory)) {
            Storage::disk('public')->deleteDirectory($directory);
        }
    }

    /**
     * Obtiene la URL pública de un archivo
     *
     * @param string $relativePath Ruta relativa del archivo
     * @return string|null
     */
    public function getPublicUrl(string $relativePath): ?string
    {
        if (empty($relativePath)) {
            return null;
        }

        return Storage::disk('public')->url($relativePath);
    }

    /**
     * Obtiene el directorio de almacenamiento para un recurso
     *
     * @param int $resourceId
     * @return string
     */
    private function getFileDirectory(int $resourceId): string
    {
        return "resources/{$resourceId}";
    }

    /**
     * Genera un nombre de archivo único preservando la extensión original
     *
     * @param UploadedFile $file
     * @return string
     */
    public function generateUniqueFilename(UploadedFile $file): string
    {
        $extension = $file->getClientOriginalExtension();
        $originalName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
        
        // Limpiar el nombre: eliminar caracteres especiales y espacios
        $name = Str::slug($originalName);
        
        // Si el nombre queda vacío después del slug, usar un nombre por defecto
        if (empty($name)) {
            $name = 'file';
        }
        
        $timestamp = now()->format('YmdHis');
        $random = Str::random(8);
        
        return "{$name}_{$timestamp}_{$random}.{$extension}";
    }

    /**
     * Obtiene la ruta relativa completa
     *
     * @param int $resourceId
     * @param string $filename
     * @return string
     */
    private function getRelativePath(int $resourceId, string $filename): string
    {
        return "resources/{$resourceId}/{$filename}";
    }
}

