<?php

namespace App\Http\Controllers;

use App\Jobs\EnviarPromocionJob;
use App\Models\Alumno;
use App\Models\Plantel;
use App\Models\Promocion;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;

class PromocionController extends Controller
{
    public function index()
    {
        $plantelesIds = $this->plantelesDelUsuario()->pluck('id');

        $promociones = Promocion::with('planteles')
            ->whereHas('planteles', fn($q) => $q->whereIn('plantels.id', $plantelesIds))
            ->latest()
            ->paginate(15);

        return view('promocion.index', compact('promociones'));
    }

    public function create()
    {
        $planteles = $this->plantelesDelUsuario();
        return view('promocion.create', compact('planteles'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'titulo'       => 'required|string|max:200',
            'descripcion'  => 'nullable|string|max:3000',
            'imagen'       => 'nullable|image|max:10240',
            'fecha_inicio' => 'required|date',
            'fecha_fin'    => 'required|date|after_or_equal:fecha_inicio',
            'status'       => 'required|in:activo,inactivo',
            'plantels'     => 'required|array|min:1',
            'plantels.*'   => 'exists:plantels,id',
        ]);

        $this->validarAccesoPlanteles($request->plantels ?? []);

        if ($request->hasFile('imagen')) {
            $data['imagen'] = $request->file('imagen')->store('promociones', 'public');
        }

        unset($data['plantels']);
        $promocion = Promocion::create($data);
        $promocion->planteles()->sync($request->plantels);

        return redirect()->route('promocion.index')->with('success', 'Promoción creada correctamente.');
    }

    public function edit(Promocion $promocion)
    {
        $this->autorizarPlantel($promocion);
        $planteles          = $this->plantelesDelUsuario();
        $plantelesSeleccionados = $promocion->planteles->pluck('id')->toArray();
        return view('promocion.edit', compact('promocion', 'planteles', 'plantelesSeleccionados'));
    }

    public function update(Request $request, Promocion $promocion)
    {
        $this->autorizarPlantel($promocion);

        $data = $request->validate([
            'titulo'       => 'required|string|max:200',
            'descripcion'  => 'nullable|string|max:3000',
            'imagen'       => 'nullable|image|max:10240',
            'fecha_inicio' => 'required|date',
            'fecha_fin'    => 'required|date|after_or_equal:fecha_inicio',
            'status'       => 'required|in:activo,inactivo',
            'plantels'     => 'required|array|min:1',
            'plantels.*'   => 'exists:plantels,id',
        ]);

        $this->validarAccesoPlanteles($request->plantels ?? []);

        if ($request->hasFile('imagen')) {
            if ($promocion->imagen) {
                Storage::disk('public')->delete($promocion->imagen);
            }
            $data['imagen'] = $request->file('imagen')->store('promociones', 'public');
        } elseif ($request->boolean('remove_imagen') && $promocion->imagen) {
            Storage::disk('public')->delete($promocion->imagen);
            $data['imagen'] = null;
        }

        unset($data['plantels']);
        $promocion->update($data);
        $promocion->planteles()->sync($request->plantels);

        return redirect()->route('promocion.index')->with('success', 'Promoción actualizada.');
    }

    public function destroy(Promocion $promocion)
    {
        $this->autorizarPlantel($promocion);

        if ($promocion->imagen) {
            Storage::disk('public')->delete($promocion->imagen);
        }

        $promocion->delete();

        return back()->with('success', 'Promoción eliminada.');
    }

    public function toggleStatus(Promocion $promocion)
    {
        $this->autorizarPlantel($promocion);

        $nuevoStatus = $promocion->status === 'activo' ? 'inactivo' : 'activo';
        $promocion->update(['status' => $nuevoStatus]);

        return back()->with('success', $nuevoStatus === 'activo' ? 'Promoción activada.' : 'Promoción desactivada.');
    }

    public function enviar(Promocion $promocion)
    {
        $this->autorizarPlantel($promocion);

        $plantelesIds = $promocion->planteles->pluck('id');

        $prospectos = Alumno::where('status', 1)
            ->where('opt_out', false)
            ->whereHas('alumnos.plantelUsuarios', function ($q) use ($plantelesIds) {
                $q->whereIn('plantels.id', $plantelesIds);
            })
            ->get();

        $despachados = 0;

        foreach ($prospectos as $i => $alumno) {
            if (!$promocion->alumnos()->where('alumno_id', $alumno->id)->exists()) {
                $promocion->alumnos()->attach($alumno->id, ['status_envio' => 'pendiente']);
            }

            EnviarPromocionJob::dispatch($promocion, $alumno)
                ->delay(now()->addSeconds($i * 2));

            $despachados++;
        }

        if ($despachados === 0) {
            return back()->with('swal', [
                'icon'  => 'warning',
                'title' => 'Sin destinatarios',
                'text'  => 'No se encontraron prospectos activos para los planteles de esta promoción.',
            ]);
        }

        return back()->with('swal', [
            'icon'  => 'success',
            'title' => '¡Enviado!',
            'text'  => "Se programó el envío para {$despachados} prospecto(s).",
        ]);
    }

    private function plantelesDelUsuario()
    {
        return Auth::user()->plantelUsuarios;
    }

    private function autorizarPlantel(Promocion $promocion): void
    {
        $ids = $this->plantelesDelUsuario()->pluck('id');
        $tieneAcceso = $promocion->planteles->pluck('id')->intersect($ids)->isNotEmpty();

        if (!$tieneAcceso) {
            abort(403);
        }
    }

    private function validarAccesoPlanteles(array $plantelIds): void
    {
        $permitidos = $this->plantelesDelUsuario()->pluck('id');

        foreach ($plantelIds as $id) {
            if (!$permitidos->contains($id)) {
                abort(403, 'No tienes acceso a uno de los planteles seleccionados.');
            }
        }
    }
}
