<?php

namespace Modules\Admin\App\Services;

use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManager;
use Modules\Admin\App\Models\Setting;

class WebsiteSettingsService
{
    private $driver;
    private $imageDisk           = 'public';
    private $favicon_basePath    = 'favicon/';
    private $image_logo_basePath = 'images/logo/';

    private $faviconsSizes = [
        '180x180' => [180, 180],
        '192x192' => [192, 192],
        '152x152' => [152, 152],
        '120x120' => [120, 120],
        '76x76' => [76, 76],
        '16x16' => [16, 16],
    ];

    private $imageLogoMaxPixels1 =  22500; // Primera versión (px^2)
    private $imageLogoMaxPixels2 =  75625; // Segunda versión (px^2) en Base64
    private $imageLogoMaxPixels3 = 230400; // Tercera versión (px^2)

    protected $cacheTTL = 60 * 24 * 30; // 30 días en minutos

    public function __construct()
    {
        $this->driver = config('image.driver', 'gd');
    }

    public function updateSetting(string $key, string $value): bool
    {
        $setting = Setting::updateOrCreate(
            ['key' => $key],
            ['value' => trim($value)]
        );

        return $setting->save();
    }

    public function processAndSaveFavicon($image): void
    {
        Storage::makeDirectory($this->imageDisk . '/' . $this->favicon_basePath);

        // Eliminar favicons antiguos
        $this->deleteOldFavicons();

        // Guardar imagen original
        $imageManager = new ImageManager($this->driver);

        $imageName = uniqid('website_favicon_');

        $image = $imageManager->read($image->getRealPath());

        foreach ($this->faviconsSizes as $size => [$width, $height]) {
            $resizedPath = $this->favicon_basePath . $imageName . "_{$size}.png";

            $image->cover($width, $height);

            Storage::disk($this->imageDisk)->put($resizedPath, $image->toPng(indexed: true));
        }

        $this->updateSetting('website_favicon_ns', $this->favicon_basePath . $imageName);
    }

    protected function deleteOldFavicons(): void
    {
        // Obtener el favicon actual desde la base de datos
        $currentFavicon = Setting::where('key', 'website_favicon')->value('value');

        if ($currentFavicon) {
            $filePaths = [
                $this->imageDisk . '/' . $currentFavicon,
                $this->imageDisk . '/' . $currentFavicon . '_16x16.png',
                $this->imageDisk . '/' . $currentFavicon . '_192x192.png',
                $this->imageDisk . '/' . $currentFavicon . '_76x76.png',
                $this->imageDisk . '/' . $currentFavicon . '_120x120.png',
                $this->imageDisk . '/' . $currentFavicon . '_152x152.png',
                $this->imageDisk . '/' . $currentFavicon . '_180x180.png',
            ];

            foreach ($filePaths as $filePath) {
                if (Storage::exists($filePath)) {
                    Storage::delete($filePath);
                }
            }
        }
    }

    public function processAndSaveImageLogo($image, string $type = ''): void
    {
        // Crear directorio si no existe
        Storage::makeDirectory($this->imageDisk . '/' . $this->image_logo_basePath);

        // Eliminar imágenes antiguas
        $this->deleteOldImageWebapp($type);

        // Leer imagen original
        $imageManager = new ImageManager($this->driver);
        $image = $imageManager->read($image->getRealPath());

        // Generar tres versiones con diferentes áreas máximas
        $this->generateAndSaveImage($image, $type, $this->imageLogoMaxPixels1, 'small'); // Versión 1
        $this->generateAndSaveImage($image, $type, $this->imageLogoMaxPixels2, 'medium'); // Versión 2
        $this->generateAndSaveImage($image, $type, $this->imageLogoMaxPixels3); // Versión 3
        $this->generateAndSaveImageAsBase64($image, $type, $this->imageLogoMaxPixels3); // Versión 3
    }

    private function generateAndSaveImage($image, string $type, int $maxPixels, string $suffix = ''): void
    {
        $imageClone = clone $image;

        // Escalar imagen conservando aspecto
        $this->resizeImageToMaxPixels($imageClone, $maxPixels);

        $imageName = 'website_image_logo' . ($suffix ? '_' . $suffix : '') . ($type == 'dark' ? '_dark' : '');

        // Generar nombre y ruta
        $imageNameUid = uniqid($imageName .  '_',  ".png");
        $resizedPath = $this->image_logo_basePath . $imageNameUid;

        // Guardar imagen en PNG
        Storage::disk($this->imageDisk)->put($resizedPath, $imageClone->toPng(indexed: true));

        // Actualizar configuración
        $this->updateSetting($imageName, $resizedPath);
    }

    private function resizeImageToMaxPixels($image, int $maxPixels)
    {
        // Obtener dimensiones originales de la imagen
        $originalWidth = $image->width();  // Método para obtener el ancho
        $originalHeight = $image->height(); // Método para obtener el alto

        // Calcular el aspecto
        $aspectRatio = $originalWidth / $originalHeight;

        // Calcular dimensiones redimensionadas conservando aspecto
        if ($aspectRatio > 1) { // Ancho es dominante
            $newWidth = sqrt($maxPixels * $aspectRatio);
            $newHeight = $newWidth / $aspectRatio;
        } else { // Alto es dominante
            $newHeight = sqrt($maxPixels / $aspectRatio);
            $newWidth = $newHeight * $aspectRatio;
        }

        // Redimensionar la imagen
        $image->resize(
            round($newWidth), // Redondear para evitar problemas con números decimales
            round($newHeight),
            function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            }
        );

        return $image;
    }


    private function generateAndSaveImageAsBase64($image, string $type, int $maxPixels): void
    {
        $imageClone = clone $image;

        // Redimensionar imagen conservando el aspecto
        $this->resizeImageToMaxPixels($imageClone, $maxPixels);

        // Convertir a Base64
        $base64Image = (string) $imageClone->toJpg(40)->toDataUri();

        // Guardar como configuración
        $this->updateSetting(
            "website_image_logo_base64" . ($type === 'dark' ? '_dark' : ''),
            $base64Image // Ya incluye "data:image/png;base64,"
        );
    }


    protected function deleteOldImageWebapp(string $type = ''): void
    {
        // Determinar prefijo según el tipo (normal o dark)
        $suffix = $type === 'dark' ? '_dark' : '';

        // Claves relacionadas con las imágenes que queremos limpiar
        $imageKeys = [
            "website_image_logo{$suffix}",
            "website_image_logo_small{$suffix}",
            "website_image_logo_medium{$suffix}",
            "website_image_logo_base64{$suffix}",
        ];

        foreach ($imageKeys as $key) {
            // Obtener la ruta de la imagen actual desde la base de datos
            $currentImage = Setting::where('key', $key)->value('value');

            // Si es una imagen en disco, eliminarla
            if ($currentImage && !str_starts_with($currentImage, 'data:image')) {
                $filePath = $this->imageDisk . '/' . $currentImage;
                if (Storage::exists($filePath)) {
                    Storage::delete($filePath);
                }
            }

            // Opcional: Eliminar la configuración de la base de datos
            Setting::where('key', $key)->delete();
        }
    }
}