<?php

namespace App\Services\ScssCdn;

use ZipArchive;
use Illuminate\Support\Facades\Log;

class ScssCdnZipService
{
    /**
     * Tamaño máximo del archivo ZIP (50MB)
     */
    private const MAX_FILE_SIZE = 50 * 1024 * 1024;

    /**
     * Descomprime un archivo ZIP y retorna estructura de archivos
     *
     * @param string $zipPath Ruta al archivo ZIP
     * @return array Array con estructura ['relative_path' => 'content', ...]
     * @throws \Exception
     */
    public static function extractZip(string $zipPath): array
    {
        if (!file_exists($zipPath)) {
            throw new \Exception('El archivo ZIP no existe.');
        }

        // Validar tamaño
        $fileSize = filesize($zipPath);
        if ($fileSize > self::MAX_FILE_SIZE) {
            throw new \Exception('El archivo ZIP excede el tamaño máximo de 50MB.');
        }

        $zip = new ZipArchive();
        $result = $zip->open($zipPath);

        if ($result !== true) {
            throw new \Exception('No se pudo abrir el archivo ZIP. Código de error: ' . $result);
        }

        $files = [];
        $invalidFiles = [];

        // Validar estructura antes de extraer
        for ($i = 0; $i < $zip->numFiles; $i++) {
            $entryName = $zip->getNameIndex($i);
            
            // Ignorar directorios
            if (substr($entryName, -1) === '/') {
                continue;
            }

            // Validar que sea archivo .scss
            $extension = strtolower(pathinfo($entryName, PATHINFO_EXTENSION));
            if ($extension !== 'scss') {
                $invalidFiles[] = $entryName;
                continue;
            }

            // Leer contenido del archivo
            $content = $zip->getFromIndex($i);
            if ($content === false) {
                Log::warning("No se pudo leer el contenido del archivo: {$entryName}");
                continue;
            }

            // Normalizar ruta (usar / como separador)
            $normalizedPath = str_replace('\\', '/', $entryName);
            $files[$normalizedPath] = $content;
        }

        $zip->close();

        // Si hay archivos inválidos, lanzar excepción
        if (!empty($invalidFiles)) {
            throw new \Exception(
                'El ZIP contiene archivos que no son .scss: ' . implode(', ', array_slice($invalidFiles, 0, 5)) .
                (count($invalidFiles) > 5 ? ' y ' . (count($invalidFiles) - 5) . ' más.' : '')
            );
        }

        if (empty($files)) {
            throw new \Exception('El archivo ZIP no contiene archivos .scss válidos.');
        }

        return $files;
    }

    /**
     * Valida la estructura del ZIP
     *
     * @param string $zipPath Ruta al archivo ZIP
     * @return array ['valid' => bool, 'errors' => array, 'file_count' => int]
     */
    public static function validateZipStructure(string $zipPath): array
    {
        $errors = [];
        $fileCount = 0;

        if (!file_exists($zipPath)) {
            return [
                'valid' => false,
                'errors' => ['El archivo ZIP no existe.'],
                'file_count' => 0,
            ];
        }

        // Validar tamaño
        $fileSize = filesize($zipPath);
        if ($fileSize > self::MAX_FILE_SIZE) {
            $errors[] = 'El archivo ZIP excede el tamaño máximo de 50MB.';
        }

        $zip = new ZipArchive();
        $result = $zip->open($zipPath);

        if ($result !== true) {
            $errors[] = 'No se pudo abrir el archivo ZIP.';
            return [
                'valid' => false,
                'errors' => $errors,
                'file_count' => 0,
            ];
        }

        $invalidFiles = [];
        $scssFiles = [];

        for ($i = 0; $i < $zip->numFiles; $i++) {
            $entryName = $zip->getNameIndex($i);
            
            // Ignorar directorios
            if (substr($entryName, -1) === '/') {
                continue;
            }

            $fileCount++;
            $extension = strtolower(pathinfo($entryName, PATHINFO_EXTENSION));
            
            if ($extension === 'scss') {
                $scssFiles[] = $entryName;
            } else {
                $invalidFiles[] = $entryName;
            }
        }

        $zip->close();

        if (!empty($invalidFiles)) {
            $errors[] = 'El ZIP contiene archivos que no son .scss: ' . count($invalidFiles) . ' archivo(s).';
        }

        if (empty($scssFiles)) {
            $errors[] = 'El archivo ZIP no contiene archivos .scss válidos.';
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors,
            'file_count' => $fileCount,
            'scss_count' => count($scssFiles),
        ];
    }

    /**
     * Procesa archivos extraídos y crea estructura de datos
     *
     * @param array $extractedFiles Array con estructura ['relative_path' => 'content', ...]
     * @return array Array procesado con información adicional
     */
    public static function processExtractedFiles(array $extractedFiles): array
    {
        $processed = [];

        foreach ($extractedFiles as $relativePath => $content) {
            // Normalizar ruta
            $normalizedPath = str_replace('\\', '/', $relativePath);
            $normalizedPath = ltrim($normalizedPath, '/');

            // Extraer nombre del archivo
            $filename = basename($normalizedPath);
            
            // Extraer directorio
            $directory = dirname($normalizedPath);
            if ($directory === '.') {
                $directory = '';
            }

            $processed[] = [
                'relative_path' => $normalizedPath,
                'filename' => $filename,
                'directory' => $directory,
                'content' => $content,
                'size' => strlen($content),
            ];
        }

        // Ordenar por ruta
        usort($processed, function ($a, $b) {
            return strcmp($a['relative_path'], $b['relative_path']);
        });

        return $processed;
    }
}

