<?php

namespace App\Livewire;

use App\Models\Evaluacion;
use App\Models\EvaluacionTipo;
use App\Models\Nivel;
use App\Models\Plantel;
use App\Models\Pregunta;
use App\Models\PreguntaOpcion;
use App\Models\PreguntaTipo;
use Illuminate\Support\Facades\DB;
use Livewire\Component;

class EvaluacionBuilder extends Component
{
    public ?int $evaluacionId = null;

    public string $titulo       = '';
    public string $descripcion  = '';
    public string $evaluacionTipoId = '';
    public string $status       = 'borrador';
    public string $fechaInicio  = '';
    public string $fechaFin     = '';
    public bool   $anonima      = false;

    public array $selectedPlanteles = [];
    public array $selectedNiveles   = [];
    public array $preguntas         = [];

    // Catálogos cargados en mount (solo lectura en la vista)
    public array $tipos        = [];
    public array $preguntaTipos = [];
    public array $planteles    = [];
    public array $niveles      = [];

    public function mount($evaluacion = null): void
    {
        $this->tipos        = EvaluacionTipo::all(['id', 'nombre', 'slug'])->toArray();
        $this->preguntaTipos = PreguntaTipo::all(['id', 'nombre', 'slug'])->toArray();
        $this->planteles    = Plantel::orderBy('name')->get(['id', 'name'])->toArray();
        $this->niveles      = Nivel::orderBy('name')->get(['id', 'name'])->toArray();

        if ($evaluacion instanceof Evaluacion && $evaluacion->exists) {
            $this->evaluacionId      = $evaluacion->id;
            $this->titulo            = $evaluacion->titulo;
            $this->descripcion       = $evaluacion->descripcion ?? '';
            $this->evaluacionTipoId  = (string) $evaluacion->evaluacion_tipo_id;
            $this->status            = $evaluacion->status;
            $this->fechaInicio       = $evaluacion->fecha_inicio?->format('Y-m-d') ?? '';
            $this->fechaFin          = $evaluacion->fecha_fin?->format('Y-m-d') ?? '';
            $this->anonima           = (bool) $evaluacion->anonima;
            $this->selectedPlanteles = $evaluacion->planteles->pluck('id')->map(fn($v) => (string) $v)->toArray();
            $this->selectedNiveles   = $evaluacion->niveles->pluck('id')->map(fn($v) => (string) $v)->toArray();

            $this->preguntas = $evaluacion->preguntas->map(fn($p) => [
                'id'               => $p->id,
                'texto'            => $p->texto,
                'pregunta_tipo_id' => (string) $p->pregunta_tipo_id,
                'requerida'        => (bool) $p->requerida,
                'es_docente'       => (bool) $p->es_docente,
                'opciones'         => $p->opciones->map(fn($o) => [
                    'id'    => $o->id,
                    'texto' => $o->texto,
                ])->toArray(),
            ])->toArray();
        }
    }

    public function addPregunta(): void
    {
        $defaultTipo = $this->preguntaTipos[0]['id'] ?? '';
        $this->preguntas[] = [
            'id'               => null,
            'texto'            => '',
            'pregunta_tipo_id' => (string) $defaultTipo,
            'requerida'        => true,
            'es_docente'       => false,
            'opciones'         => [],
        ];
    }

    public function removePregunta(int $index): void
    {
        array_splice($this->preguntas, $index, 1);
        $this->preguntas = array_values($this->preguntas);
    }

    public function movePregunta(int $index, string $direction): void
    {
        $swap = $direction === 'up' ? $index - 1 : $index + 1;

        if ($swap < 0 || $swap >= count($this->preguntas)) {
            return;
        }

        [$this->preguntas[$index], $this->preguntas[$swap]] = [$this->preguntas[$swap], $this->preguntas[$index]];
    }

    public function addOpcion(int $preguntaIndex): void
    {
        $this->preguntas[$preguntaIndex]['opciones'][] = ['id' => null, 'texto' => ''];
    }

    public function removeOpcion(int $preguntaIndex, int $opcionIndex): void
    {
        array_splice($this->preguntas[$preguntaIndex]['opciones'], $opcionIndex, 1);
        $this->preguntas[$preguntaIndex]['opciones'] = array_values($this->preguntas[$preguntaIndex]['opciones']);
    }

    public function guardar(): void
    {
        $this->validate([
            'titulo'                           => 'required|string|max:255',
            'descripcion'                      => 'nullable|string',
            'evaluacionTipoId'                 => 'required|exists:evaluacion_tipos,id',
            'status'                           => 'required|in:borrador,activa,cerrada',
            'fechaInicio'                      => 'nullable|date',
            'fechaFin'                         => 'nullable|date',
            'selectedPlanteles'                => 'array',
            'selectedNiveles'                  => 'array',
            'preguntas'                        => 'required|array|min:1',
            'preguntas.*.texto'                => 'required|string|max:1000',
            'preguntas.*.pregunta_tipo_id'     => 'required|exists:pregunta_tipos,id',
            'preguntas.*.opciones.*.texto'     => 'required|string|max:500',
        ], [
            'titulo.required'                      => 'El título es obligatorio.',
            'evaluacionTipoId.required'            => 'Selecciona el tipo de evaluación.',
            'preguntas.required'                   => 'Agrega al menos una pregunta.',
            'preguntas.min'                        => 'Agrega al menos una pregunta.',
            'preguntas.*.texto.required'           => 'El texto de la pregunta es obligatorio.',
            'preguntas.*.pregunta_tipo_id.required' => 'Selecciona el tipo de respuesta.',
            'preguntas.*.opciones.*.texto.required' => 'El texto de la opción es obligatorio.',
        ]);

        DB::transaction(function () {
            $data = [
                'titulo'              => $this->titulo,
                'descripcion'         => $this->descripcion ?: null,
                'evaluacion_tipo_id'  => $this->evaluacionTipoId,
                'status'              => $this->status,
                'fecha_inicio'        => $this->fechaInicio ?: null,
                'fecha_fin'           => $this->fechaFin ?: null,
                'anonima'             => $this->anonima,
            ];

            if ($this->evaluacionId) {
                $evaluacion = Evaluacion::findOrFail($this->evaluacionId);
                $evaluacion->update($data);
            } else {
                $evaluacion = Evaluacion::create($data);
                $this->evaluacionId = $evaluacion->id;
            }

            $evaluacion->planteles()->sync($this->selectedPlanteles);
            $evaluacion->niveles()->sync($this->selectedNiveles);

            // Eliminar preguntas removidas
            $keptIds = collect($this->preguntas)->pluck('id')->filter()->values()->toArray();
            $evaluacion->preguntas()->whereNotIn('id', $keptIds)->delete();

            foreach ($this->preguntas as $orden => $pData) {
                if (!empty($pData['id'])) {
                    $pregunta = Pregunta::findOrFail($pData['id']);
                    $pregunta->update([
                        'texto'            => $pData['texto'],
                        'pregunta_tipo_id' => $pData['pregunta_tipo_id'],
                        'requerida'        => $pData['requerida'] ?? true,
                        'es_docente'       => $pData['es_docente'] ?? false,
                        'orden'            => $orden,
                    ]);
                } else {
                    $pregunta = $evaluacion->preguntas()->create([
                        'texto'            => $pData['texto'],
                        'pregunta_tipo_id' => $pData['pregunta_tipo_id'],
                        'requerida'        => $pData['requerida'] ?? true,
                        'es_docente'       => $pData['es_docente'] ?? false,
                        'orden'            => $orden,
                    ]);
                }

                $tipoSlug = collect($this->preguntaTipos)
                    ->firstWhere('id', (int) $pData['pregunta_tipo_id'])['slug'] ?? '';

                if ($tipoSlug === 'opcion_multiple') {
                    $keptOpcionIds = collect($pData['opciones'] ?? [])
                        ->pluck('id')->filter()->values()->toArray();
                    $pregunta->opciones()->whereNotIn('id', $keptOpcionIds)->delete();

                    foreach ($pData['opciones'] ?? [] as $opOrden => $opData) {
                        if (!empty($opData['id'])) {
                            PreguntaOpcion::findOrFail($opData['id'])->update([
                                'texto' => $opData['texto'],
                                'orden' => $opOrden,
                            ]);
                        } else {
                            $pregunta->opciones()->create([
                                'texto' => $opData['texto'],
                                'orden' => $opOrden,
                            ]);
                        }
                    }
                } else {
                    $pregunta->opciones()->delete();
                }
            }
        });

        session()->flash('info', 'Evaluación guardada correctamente.');
        $this->redirect(route('evaluacion.index'));
    }

    public function render()
    {
        return view('livewire.evaluacion-builder');
    }
}
