<?php

namespace App\Http\Controllers;

use App\Models\Calendario;
use App\Models\CentroCosto;
use App\Models\ComentarioTiempo;
use App\Models\Empleado;
use App\Models\EntradaTiempo;
use App\Models\HojaTiempo;
use App\Models\Periodo;
use App\Services\HojaTiempoService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class HojaTiempoController extends Controller
{
    public function __construct(protected HojaTiempoService $service) {}

    /**
     * Lista de hojas del período activo (vista tipo Index del Excel)
     */
    public function index(Request $request)
    {
        $user = Auth::user();

        // EMPLEADO y SST: ir directo a su propia hoja del período activo
        // SST puede ver reportes por el sidebar pero no gestiona el listado
        if (!$user->esSupervisor()) {
            $periodo = Periodo::activo()->first();
            if (!$periodo) {
                return view('hojas-tiempo.sin-periodo');
            }
            if (!$user->empleado_id) {
                return back()->with('error', 'Tu usuario no tiene un empleado asociado.');
            }
            $hoja = HojaTiempo::firstOrCreate(
                ['empleado_id' => $user->empleado_id, 'periodo_id' => $periodo->id],
                ['estado' => 'borrador']
            );
            return redirect()->route('hojas-tiempo.show', $hoja);
        }

        // SUPERVISOR / ADMIN: ver listado completo
        $periodoActivo = Periodo::activo()->first();
        $periodos = Periodo::orderByDesc('anio')->orderByDesc('mes')->get();
        $periodoSeleccionado = $request->periodo_id
            ? Periodo::find($request->periodo_id)
            : $periodoActivo;

        $hojas = collect();
        if ($periodoSeleccionado) {
            $hojas = HojaTiempo::with('empleado')
                ->where('periodo_id', $periodoSeleccionado->id)
                ->orderBy('estado')
                ->get();
        }

        $conHoja = $hojas->pluck('empleado_id');
        $sinHoja = $periodoSeleccionado
            ? Empleado::activos()->whereNotIn('id', $conHoja)->get()
            : collect();

        $consolidado = collect();
        if ($periodoSeleccionado) {
            $consolidado = $this->service->consolidadoPeriodo($periodoSeleccionado);
        }

        $stats = [
            'aprobadas'  => $hojas->where('estado', 'aprobado')->count(),
            'enviadas'   => $hojas->where('estado', 'enviado')->count(),
            'borradores' => $hojas->where('estado', 'borrador')->count(),
            'sin_hoja'   => $sinHoja->count(),
        ];

        return view('hojas-tiempo.index', compact(
            'hojas', 'periodoSeleccionado', 'periodos', 'sinHoja', 'stats', 'consolidado'
        ));
    }

    /**
     * Mostrar la grilla de ingreso de horas de un empleado en un período
     */
    public function show(HojaTiempo $hojaTiempo)
    {
        $hojaTiempo->load(['empleado', 'periodo']);
        $grilla = $this->service->construirGrilla($hojaTiempo);
        $resumen = $this->service->calcularResumen($hojaTiempo);

        return view('hojas-tiempo.show', compact('hojaTiempo', 'grilla', 'resumen'));
    }

    /**
     * Crear hoja para un empleado (desde el listado)
     */
    public function crear(Request $request)
    {
        $request->validate([
            'empleado_id' => 'required|exists:empleados,id',
            'periodo_id'  => 'required|exists:periodos,id',
        ]);

        $hoja = HojaTiempo::firstOrCreate([
            'empleado_id' => $request->empleado_id,
            'periodo_id'  => $request->periodo_id,
        ], ['estado' => 'borrador']);

        return redirect()->route('hojas-tiempo.show', $hoja);
    }

    /**
     * Guardar horas via AJAX (celda por celda en la grilla)
     */
    public function guardarEntrada(Request $request, HojaTiempo $hojaTiempo): JsonResponse
    {
        $data = $request->validate([
            'centro_costo_id' => 'required|exists:centros_costo,id',
            'fecha'           => 'required|date',
            'horas'           => 'required|numeric|min:0|max:24',
        ]);

        if ($hojaTiempo->estado === 'aprobado') {
            return response()->json(['error' => 'La hoja ya está aprobada y no se puede modificar.'], 403);
        }

        try {
            $this->service->guardarEntrada($hojaTiempo, $data);

            // Recalcular totales del día y columnas
            $totalDia = EntradaTiempo::where('hoja_tiempo_id', $hojaTiempo->id)
                ->where('fecha', $data['fecha'])
                ->sum('horas');

            $resumen = $this->service->calcularResumen($hojaTiempo);

            return response()->json([
                'success'   => true,
                'total_dia' => $totalDia,
                'resumen'   => [
                    'total_horas'       => $resumen['total_horas'],
                    'horas_exentas'     => $resumen['horas_exentas'],
                    'horas_productivas' => $resumen['horas_productivas'],
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    /**
     * Guardar toda la grilla en lote (botón "Guardar Todo")
     */
    public function guardarGrilla(Request $request, HojaTiempo $hojaTiempo)
    {
        $request->validate([
            'entradas'                  => 'required|array',
            'entradas.*.centro_costo_id'=> 'required|exists:centros_costo,id',
            'entradas.*.fecha'          => 'required|date',
            'entradas.*.horas'          => 'required|numeric|min:0|max:24',
        ]);

        if ($hojaTiempo->estado === 'aprobado') {
            return back()->with('error', 'La hoja ya está aprobada.');
        }

        $this->service->guardarGrilla($hojaTiempo, $request->entradas);

        return back()->with('success', 'Horas guardadas correctamente.');
    }

    /**
     * Guardar varias celdas en UN solo request (AJAX) y devolver el resumen
     * recalculado. Reemplaza el guardado celda-por-celda para mayor velocidad.
     */
    public function guardarLote(Request $request, HojaTiempo $hojaTiempo): JsonResponse
    {
        $request->validate([
            'entradas'                   => 'present|array',
            'entradas.*.centro_costo_id' => 'required|exists:centros_costo,id',
            'entradas.*.fecha'           => 'required|date',
            'entradas.*.horas'           => 'required|numeric|min:0|max:24',
        ]);

        if ($hojaTiempo->estado === 'aprobado') {
            return response()->json(['error' => 'La hoja ya está aprobada y no se puede modificar.'], 403);
        }

        try {
            $this->service->guardarGrilla($hojaTiempo, $request->entradas ?? []);

            // Totales por día (una sola consulta)
            $totalesDia = EntradaTiempo::where('hoja_tiempo_id', $hojaTiempo->id)
                ->selectRaw('fecha, SUM(horas) as total')
                ->groupBy('fecha')
                ->pluck('total', 'fecha')
                ->map(fn ($v) => (float) $v);

            $resumen = $this->service->calcularResumen($hojaTiempo);

            return response()->json([
                'success'     => true,
                'totales_dia' => $totalesDia,
                'resumen'     => [
                    'total_horas'       => $resumen['total_horas'],
                    'horas_exentas'     => $resumen['horas_exentas'],
                    'horas_productivas' => $resumen['horas_productivas'],
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    /**
     * Enviar hoja para aprobación
     */
    public function enviar(HojaTiempo $hojaTiempo)
    {
        if ($hojaTiempo->estado !== 'borrador') {
            return back()->with('error', 'Solo se pueden enviar hojas en estado borrador.');
        }
        $this->service->enviar($hojaTiempo);
        return back()->with('success', 'Hoja enviada para aprobación.');
    }

    /**
     * Aprobar hoja (supervisor/admin)
     */
    public function aprobar(HojaTiempo $hojaTiempo)
    {
        $this->service->aprobar($hojaTiempo, Auth::id());
        return back()->with('success', 'Hoja aprobada.');
    }

    /**
     * Devolver hoja a borrador
     */
    public function devolver(HojaTiempo $hojaTiempo)
    {
        $this->service->devolver($hojaTiempo);
        return back()->with('success', 'Hoja devuelta a borrador.');
    }

    /**
     * Agregar comentario a una entrada (equivalente a comentarios de celda del Excel)
     */
    public function comentar(Request $request, EntradaTiempo $entrada): JsonResponse
    {
        $request->validate(['comentario' => 'required|string|max:500']);

        $comentario = ComentarioTiempo::create([
            'entrada_tiempo_id' => $entrada->id,
            'comentario'        => $request->comentario,
            'user_id'           => Auth::id(),
        ]);

        return response()->json([
            'success'    => true,
            'comentario' => $comentario->comentario,
            'autor'      => Auth::user()->name,
            'fecha'      => $comentario->created_at->format('d/m/Y H:i'),
        ]);
    }


    /**
     * Limpiar hoja: borra todas las entradas y vuelve a borrador (solo supervisor)
     */
    public function limpiar(HojaTiempo $hojaTiempo)
    {
        if (!Auth::user()->esSupervisor()) abort(403);

        DB::transaction(function () use ($hojaTiempo) {
            // Borrar comentarios primero
            foreach ($hojaTiempo->entradas as $entrada) {
                $entrada->comentarios()->delete();
            }
            $hojaTiempo->entradas()->delete();
            $hojaTiempo->update([
                'estado'       => 'borrador',
                'enviado_at'   => null,
                'aprobado_at'  => null,
                'aprobado_por' => null,
            ]);
        });

        return back()->with('success', 'Hoja limpiada — todas las entradas fueron eliminadas.');
    }

    /**
     * Eliminar hoja completamente (solo supervisor)
     */
    public function eliminar(HojaTiempo $hojaTiempo)
    {
        if (!Auth::user()->esSupervisor()) abort(403);

        DB::transaction(function () use ($hojaTiempo) {
            foreach ($hojaTiempo->entradas as $entrada) {
                $entrada->comentarios()->delete();
            }
            $hojaTiempo->entradas()->delete();
            $hojaTiempo->delete();
        });

        return redirect()->route('hojas-tiempo.index')
            ->with('success', 'Hoja de tiempo eliminada.');
    }

    /**
     * Distribucion de horas por CC para AJAX (expandir fila en consolidado)
     */
    /**
     * Guardar/actualizar la observacion de uso de un centro de costo en la hoja
     */
    public function guardarObservacionCC(Request $request, HojaTiempo $hojaTiempo): JsonResponse
    {
        $data = $request->validate([
            'centro_costo_id' => 'required|exists:centros_costo,id',
            'observacion'     => 'nullable|string|max:1000',
        ]);

        if ($hojaTiempo->estado === 'aprobado') {
            return response()->json(['error' => 'La hoja ya esta aprobada y no se puede modificar.'], 403);
        }

        $texto = trim($data['observacion'] ?? '');

        if ($texto === '') {
            // Vacio = eliminar la observacion
            $hojaTiempo->observacionesCC()
                ->where('centro_costo_id', $data['centro_costo_id'])
                ->delete();
            return response()->json(['success' => true, 'observacion' => null]);
        }

        $obs = \App\Models\ObservacionCentroCosto::updateOrCreate(
            [
                'hoja_tiempo_id'  => $hojaTiempo->id,
                'centro_costo_id' => $data['centro_costo_id'],
            ],
            [
                'observacion' => $texto,
                'user_id'     => Auth::id(),
            ]
        );

        return response()->json(['success' => true, 'observacion' => $obs->observacion]);
    }

    public function distribucion(HojaTiempo $hojaTiempo)
    {
        $resumen = $this->service->calcularResumen($hojaTiempo);
        return response()->json($resumen['distribucion']->values());
    }

    /**
     * Obtener comentarios de una entrada
     */
    public function comentarios(EntradaTiempo $entrada): JsonResponse
    {
        $comentarios = $entrada->comentarios()->with('user')->orderBy('created_at')->get();
        return response()->json($comentarios->map(fn ($c) => [
            'comentario' => $c->comentario,
            'autor'      => $c->user->name,
            'fecha'      => $c->created_at->format('d/m/Y H:i'),
        ]));
    }
}