<?php

namespace App\Livewire\ScssCdn;

use App\Models\Products\Product;
use App\Models\ScssCdn\ScssCdnBundle;
use App\Models\ScssCdn\ScssCdnFile;
use App\Services\ScssCdn\ScssCdnStorageService;
use App\Services\ScssCdn\ScssCdnZipService;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Str;

class ZipUpload extends Component
{
    use WithFileUploads;

    public Product $product;
    public ScssCdnBundle $bundle;
    public $zipFile;
    public $uploadStatus = null;
    public $processedFiles = [];

    public function mount(Product $product, ScssCdnBundle $bundle)
    {
        $this->product = $product;
        $this->bundle = $bundle->load('product');

        // Verificar que el bundle pertenezca al producto
        if ($this->bundle->product_id !== $this->product->id) {
            abort(404, 'El bundle no pertenece a este producto.');
        }
    }

    public function updatedZipFile()
    {
        $this->uploadStatus = null;
        $this->processedFiles = [];
        $this->resetErrorBag('zipFile');
    }

    public function uploadDirect()
    {
        // Método principal que llama a upload() internamente
        // Se usa uploadDirect() en lugar de upload() directamente porque
        // Livewire tiene problemas con métodos que tienen validación cuando se llaman directamente
        if (!$this->zipFile) {
            $this->uploadStatus = [
                'type' => 'error',
                'message' => 'Debe seleccionar un archivo ZIP.',
            ];
            return;
        }

        // Llamar al método upload() que contiene toda la lógica
        $this->upload();
    }


    public function upload()
    {
        try {
            // Validar que se haya seleccionado un archivo
            if (!$this->zipFile) {
                $this->uploadStatus = [
                    'type' => 'error',
                    'message' => 'Debe seleccionar un archivo ZIP.',
                ];
                return;
            }

            // Validar el archivo - usar reglas directamente
            $this->validate([
                'zipFile' => ['required', 'file', 'mimes:zip', 'max:51200'],
            ], [
                'zipFile.required' => 'Debe seleccionar un archivo ZIP.',
                'zipFile.mimes' => 'El archivo debe ser un ZIP.',
                'zipFile.max' => 'El archivo ZIP no puede exceder 50MB.',
            ]);
        } catch (\Illuminate\Validation\ValidationException $e) {
            $errorMessages = [];
            foreach ($e->errors() as $field => $messages) {
                $errorMessages = array_merge($errorMessages, $messages);
            }
            $this->uploadStatus = [
                'type' => 'error',
                'message' => 'Error de validación: ' . implode(', ', $errorMessages),
            ];
            return;
        } catch (\Exception $e) {
            Log::error('ZipUpload: Error en validación', [
                'message' => $e->getMessage(),
            ]);
            $this->uploadStatus = [
                'type' => 'error',
                'message' => 'Error: ' . $e->getMessage(),
            ];
            return;
        }

        try {
            // En Livewire, el archivo se sube automáticamente y está disponible
            // Obtener la ruta temporal del archivo
            $zipPath = $this->zipFile->getRealPath();

            // Si no está disponible, intentar obtenerlo del storage temporal
            if (!$zipPath || !file_exists($zipPath)) {
                // El archivo puede estar en el storage temporal de Livewire
                $zipPath = $this->zipFile->path();
            }

            if (!$zipPath || !file_exists($zipPath)) {
                Log::error('ZipUpload: No se pudo acceder al archivo', [
                    'realPath' => $this->zipFile->getRealPath(),
                    'path' => method_exists($this->zipFile, 'path') ? $this->zipFile->path() : 'N/A',
                ]);
                $this->addError('zipFile', 'No se pudo acceder al archivo ZIP. Por favor, intente subirlo nuevamente.');
                $this->uploadStatus = [
                    'type' => 'error',
                    'message' => 'No se pudo acceder al archivo ZIP. Por favor, intente subirlo nuevamente.',
                ];
                return;
            }

            // Validar estructura del ZIP
            $validation = ScssCdnZipService::validateZipStructure($zipPath);

            if (!$validation['valid']) {
                $this->addError('zipFile', implode(' ', $validation['errors']));
                return;
            }

            // Extraer archivos del ZIP
            $extractedFiles = ScssCdnZipService::extractZip($zipPath);

            // Procesar archivos extraídos
            $processedFiles = ScssCdnZipService::processExtractedFiles($extractedFiles);

            $savedCount = 0;
            $skippedCount = 0;
            $errors = [];

            foreach ($processedFiles as $fileData) {
                try {
                    // Verificar si el archivo ya existe
                    $existingFile = ScssCdnFile::where('scss_cdn_bundle_id', $this->bundle->id)
                        ->where('relative_path', $fileData['relative_path'])
                        ->first();

                    if ($existingFile) {
                        // Actualizar archivo existente
                        $existingFile->update([
                            'updated_by' => auth()->id(),
                        ]);
                    } else {
                        // Crear nuevo archivo
                        $existingFile = ScssCdnFile::create([
                            'scss_cdn_bundle_id' => $this->bundle->id,
                            'relative_path' => $fileData['relative_path'],
                            'filename' => $fileData['filename'],
                            'is_servable' => false,
                            'secure_token' => Str::random(32),
                            'created_by' => auth()->id(),
                            'updated_by' => auth()->id(),
                        ]);
                    }

                    // Guardar archivo físico
                    $saved = ScssCdnStorageService::saveFile(
                        $this->product,
                        $this->bundle,
                        $fileData['relative_path'],
                        $fileData['content']
                    );

                    if (!$saved) {
                        $errors[] = "Error al guardar el archivo físico: {$fileData['relative_path']}";
                        if (!$existingFile->wasRecentlyCreated) {
                            // Si era un archivo nuevo, eliminarlo de BD
                            $existingFile->delete();
                        }
                    } else {
                        $savedCount++;
                        $this->processedFiles[] = [
                            'path' => $fileData['relative_path'],
                            'size' => $fileData['size'],
                            'status' => $existingFile->wasRecentlyCreated ? 'created' : 'updated',
                        ];
                    }
                } catch (\Exception $e) {
                    $errors[] = "Error al procesar {$fileData['relative_path']}: " . $e->getMessage();
                }
            }

            if ($savedCount > 0) {
                $this->uploadStatus = [
                    'type' => 'success',
                    'message' => "Se procesaron {$savedCount} archivo(s) correctamente." .
                        ($skippedCount > 0 ? " Se omitieron {$skippedCount} archivo(s)." : ''),
                ];
            }

            if (!empty($errors)) {
                $this->uploadStatus = [
                    'type' => 'warning',
                    'message' => "Se procesaron {$savedCount} archivo(s), pero hubo errores: " . implode(', ', array_slice($errors, 0, 3)),
                ];
            }

            // Recargar bundle
            $this->bundle->refresh();

            // Limpiar archivo temporal
            $this->zipFile = null;
        } catch (\Illuminate\Validation\ValidationException $e) {
            // Re-lanzar para que Livewire lo maneje
            throw $e;
        } catch (\Exception $e) {
            Log::error('ZipUpload: Error al procesar ZIP', [
                'message' => $e->getMessage(),
            ]);
            $this->addError('zipFile', 'Error al procesar el ZIP: ' . $e->getMessage());
            $this->uploadStatus = [
                'type' => 'error',
                'message' => 'Error al procesar el ZIP: ' . $e->getMessage(),
            ];
        }
    }

    public function render()
    {
        return view('livewire.scss-cdn.zip-upload', [
            'product' => $this->product,
            'bundle' => $this->bundle,
        ])->layout('layouts.clean');
    }
}
