<?php

namespace App\Services;

use App\Enums\TipoConfiguracion;
use App\Models\Configuracion;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

final class ConfiguracionService
{
    private function getKeys(Request $request): array
    {
        return array_filter(array_keys($request->all()), fn ($el) => str()->isUuid($el));
    }

    public function update(Request $request)
    {
        // Filtramos todos los UUID que estan en el request
        $claves = $this->getKeys($request);
        $configuraciones = Configuracion::whereIn('uuid', $claves)->get(['tipo', 'clave', 'display_name', 'valor', 'id', 'uuid']);

        foreach ($configuraciones as $configuracion) {
            $tipo_configuracion = TipoConfiguracion::from($configuracion->tipo);

            if ($tipo_configuracion === TipoConfiguracion::ARCHIVO || $tipo_configuracion === TipoConfiguracion::IMAGEN) {

                $url = $request->file($configuracion->uuid)->store('public/configuracion');

                if ($configuracion->valor) {
                    Storage::disk('public')->delete($configuracion->valor);
                }
                $configuracion->valor = $url;

            } else {
                $clave = $configuracion->uuid;
                $configuracion->valor = $request->get($clave);
            }
            $configuracion->save();
        }
    }

    public function getValidationRules(Request $request): array
    {
        $claves = $this->getKeys($request);
        $configuraciones = Configuracion::whereIn('uuid', $claves)->get(['tipo', 'clave', 'display_name']);

        $rules = [];
        $message = [];

        foreach ($configuraciones as $configuracion) {
            $rules[] = match ($configuracion->tipo) {
                TipoConfiguracion::ARCHIVO->value => [$configuracion->clave => ['file', 'size:512']],
                TipoConfiguracion::BOOL->value => [$configuracion->clave => ['in:true,false']],
                TipoConfiguracion::IMAGEN->value => [$configuracion->clave => ['image', 'max:100']],
                TipoConfiguracion::NUMERO->value => [$configuracion->clave => ['numeric']],
                TipoConfiguracion::TEXTO->value => [$configuracion->clave => ['string', 'nullable']]
            };
        }

        foreach ($configuraciones as $configuracion) {
            $message[] = match ($configuracion->tipo) {
                TipoConfiguracion::ARCHIVO->value => [
                    $configuracion->clave.'.file' => "$configuracion->display_name desde ser un archivo.",
                    $configuracion->clave.'.max' => "$configuracion->display_name debe tener un tamaño menor a :max kb",
                ],
                TipoConfiguracion::BOOL->value => [
                    $configuracion->clave.'.in' => "$configuracion->display_name debe ser true o false",
                ],
                TipoConfiguracion::IMAGEN->value => [
                    $configuracion->clave.'.image' => "$configuracion->display_name debe ser una imagen",
                    $configuracion->clave.'.size' => "$configuracion->display_name debe ser menor a :size kb",
                ],
                TipoConfiguracion::NUMERO->value => [
                    $configuracion->clave.'.numeric' => "$configuracion->display_name debe ser un número",
                ],
                TipoConfiguracion::TEXTO->value => [
                    $configuracion->clave.'.string' => "$configuracion->display_name debe ser una cadena de texto",
                ]
            };
        }

        return ['rules' => $this->array_flatten($rules), 'messages' => $this->array_flatten($message)];
    }

    private function array_flatten($array = null, $depth = 1)
    {
        $result = [];
        if (! is_array($array)) {
            $array = func_get_args();
        }
        foreach ($array as $key => $value) {
            if (is_array($value) && $depth) {
                $result = array_merge($result, $this->array_flatten($value, $depth - 1));
            } else {
                $result = array_merge($result, [$key => $value]);
            }
        }

        return $result;
    }
}
