<?php

namespace App\Traits;

use App\Models\ImageSetting;
use App\Models\ThumbnailSetting;
use App\Services\UploadedImageService;
use App\Services\Image\ImageService;
use Illuminate\Support\Str;
use DOMDocument;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;
use Spatie\Image\Image as SpatieImage;

use App\Models\Image as ImageModel;

trait SummernoteTrait
{
    private function is_base64($s)
    {
        return (bool) preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s);
    }

    public function formatSummernote(
        $descripcion,
        $model
    ) {

        $image_service = new ImageService;
        $image_upload = new UploadedImageService($image_service);

        /*
        ? ACCIONES
        * extraer imagenes:
            1=> con url,
            2=> a guardar (nombre.formato | base64 | alt)
            3=> url de imagenes a descargar
        * extraer texto
            Data => formateado listo para almacenar
        */

        //? Para registro de imagenes y orden
        $imagenes = array();
        $img_nuevo = 0;

        $message = mb_convert_encoding($descripcion, 'HTML-ENTITIES', 'UTF-8');

        $dom = new DOMDocument();

        libxml_use_internal_errors(true);

        $dom->loadHTML("<div>$message</div>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

        $container = $dom->getElementsByTagName('div')->item(0);

        $container = $container->parentNode->removeChild($container);

        while ($dom->firstChild) {
            $dom->removeChild($dom->firstChild);
        }

        while ($container->firstChild) {
            $dom->appendChild($container->firstChild);
        }

        $images = $dom->getElementsByTagName('img');

        $script = $dom->getElementsByTagName('script');

        $remove = [];
        foreach ($script as $item) {
            $remove[] = $item;
        }

        foreach ($remove as $item) {
            $item->parentNode->removeChild($item);
        }

        foreach ($images as $key => $img) {
            $src = $img->getAttribute('src');
            //*Imagen externa no aplica de momento

            if (!preg_match('/data:image/', $src)) {
                $imagenes[] = (object)[
                    'titulo' => $img->getAttribute('data-filename'),
                    'src' => $src,
                    'is_url' => 1,
                    'is_external' => 0,
                    'nuevo' => 0
                ];
                continue;
            }

            preg_match('/data:image\/(?<mime>.*?)\;/', $src, $groups);
            $mimetype = $groups['mime'];
            $img_name = time() + round(1, 9);

            $new_img = $this->storeImage($src, $model);

            $images[$key]->setAttribute('data-filename', $new_img->name);
            $images[$key]->removeAttribute('src');
            $images[$key]->setAttribute('src', asset($new_img->url));

            $imagenes[] = (object) [
                'titulo' => $new_img->name,
                'src' => asset($new_img->url),
                'ext' => $new_img->ext,
                'is_url' => 0,
                'is_external' => 0,
                'nuevo' => 1
            ];

            $img_nuevo++;
        }

        $descripcion = $dom->saveHTML();

        return (object) [
            'imagenes' => $imagenes,
            'descripcion' => $descripcion,
            'imagen_nuevo' => $img_nuevo
        ];
    }

    public function storeImage($base64image, $model, $size = 'summernote'): false | object
    {
        $imageSettings = ImageSetting::where('type', $model)
            ->first();
        if (!$imageSettings)
            return false;

        $thumbnailSettings = ThumbnailSetting::where('size', $size)
            ->where('image_settings_id', $imageSettings->id)
            ->first();
        if (!$thumbnailSettings)
            return false;

        $base_to_php = explode(',', $base64image);
        $image = base64_decode($base_to_php[1]);

        $imageName = Str::random();
        $to = $imageSettings->upload_to;
        $dirname =  "public/{$to}";
        $path =  "$dirname/$imageName.jpg";


        $directoryPath = public_path(trim($to));
        if (!File::exists($to)) {
            File::makeDirectory($to, 0755, true);
        }

        file_put_contents(base_path() . "/$path", $image);

        // Obtenemos las dimensiones actuales de la imagen
        $dimensions = getimagesize(base_path() . "/$path");
        $currentWidth = $dimensions[0];
        $currentHeight = $dimensions[1];

        $spatie = SpatieImage::load(base_path() . "/$path");
        if (
            $currentWidth > $thumbnailSettings->width ||
            $currentHeight > $thumbnailSettings->height
        ) {
            $spatie = $spatie->width($thumbnailSettings->width)
                ->height($thumbnailSettings->height);
        }
        $spatie->optimize();

        $newPath = "$dirname/$imageName@$size.webp";
        $spatie->save(base_path() . '/' . $newPath);

        unlink(base_path() . "/$path");

        return (object) [
            'name' => $imageName,
            'ext' => 'webp',
            'size' => $size,
            'url' => "$to/$imageName@$size.webp"
        ];
    }

    public function optimizeImageSummernote(array $images, $model, $type_id)
    {
        foreach ($images as $image) {
            if ($image->nuevo) {
                $ids[] = ImageModel::create([
                    'imageable_type' => $model,
                    'imageable_id' => $type_id,
                    'name' => $image->titulo,
                    'ext' => $image->ext,
                    'enriched_text' => true
                ]);
            }
        }

        $toDelete = ImageModel::where('imageable_type', $model)
            ->where('imageable_id', $type_id)
            ->where('enriched_text', true)
            ->where(function ($query) use ($images) {
                foreach ($images as $image) {
                    $query->where('name', '<>', $image->titulo);
                }
            })->get();

        $imageSettings = ImageSetting::where('type', $model)
            ->first();
        $thumbnailSetting = ThumbnailSetting::where('image_settings_id', $imageSettings->id)
            ->get();
        foreach ($toDelete as $image) {
            foreach ($thumbnailSetting as $setting) {
                $path = base_path() . "/public/$imageSettings->upload_to/$image->name@$setting->size.$image->ext";
                if (file_exists($path))
                    unlink($path);
                ImageModel::where('id', $image->id)
                    ->delete();
            }
        }
    }

    public function deleteSummernoteImages($model, $type_id, $all = false)
    {
        $toDelete = ImageModel::where('imageable_type', $model)
            ->where('imageable_id', $type_id)
            ->where(function ($query) use ($all) {
                if ($all)
                    $query->where('enriched_text', true);
            })
            ->get();

        $imageSettings = ImageSetting::where('type', $model)
            ->first();
        $thumbnailSetting = ThumbnailSetting::where('image_settings_id', $imageSettings->id)
            ->get();
        foreach ($toDelete as $image) {
            foreach ($thumbnailSetting as $setting) {
                $path = base_path() . "/public/$imageSettings->upload_to/$image->name@$setting->size.$image->ext";
                if (file_exists($path))
                    unlink($path);
                ImageModel::where('id', $image->id)
                    ->delete();
            }
        }
    }


    /*! NO */
    public function filtrarNombreImagen($imagen)
    {

        $temp = explode('.', $imagen);

        unset($temp[count($temp) - 1]);

        $imagen = implode('.', $temp);

        return $imagen;
    }
    private function getUrlContent($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,  FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
        $data = curl_exec($ch);
        curl_close($ch);

        return $data;
    }
    private function saveImg($imagen, $url, $name, $recorte, $mimetype = 'png')
    {
        if (!$url || !$imagen || !$mimetype || !$name) return null;
        //$imgNewName = 'external_' . (time() + round(100, 999));
        $filepath = $name . '.' . $mimetype;
        $this->createPath($url);

        $x = (int) $recorte->size_x;
        $y = (int) $recorte->size_y;

        //sacar dimenciones de la imagen
        $binary = base64_decode(explode(',', $imagen)[1]);
        $size = getimagesizefromstring($binary);


        $originalX = null;
        $originalY = null;
        if (!empty($size)) {
            $originalX = $size[0];
            $originalY = $size[1];
        } else {
            //error
            return false;
        }

        //calcula el 25% de la dimensión
        $size = ($originalX / 100) * 25;
        //dd($size, $originalX);
        /*  $watermark = Image::make('images/watermark.png')
            ->resize($size, null, function ($constraint) {
                $constraint->aspectRatio();
            });*/

        $image = Image::make($imagen)
            // resize if required
            //->resize($lstImagenes->size_x, $lstImagenes->size_y, function ($constraint) {
            ->resize($recorte->size_x, $recorte->size_y, function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            })
            //->insert($watermark, 'bottom-right', 15, 15)
            ->encode($mimetype, 100)
            ->save(public_path($url . $filepath));
        //file_put_contents($url . $imgNewName, $imagen);

        return [
            'titulo' => $filepath,
            'url' => $url . $filepath
        ];
    }
    private function createPath($path)
    {
        // Crea el directorio de almacenamiento si no existe
        $directoryPath = public_path(trim($path));
        if (!File::exists($directoryPath)) {
            File::makeDirectory($directoryPath, 0755, true);
        }
        return;
    }
}
