<?php

namespace App\Http\Controllers;

use App\Models\Diferencia;
use App\Models\PrecioDia;
use App\Models\TipoCombustible;
use App\Models\Turno;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

class DiferenciasController extends Controller
{
    public function index(Request $request)
    {
        $query = Diferencia::with(['turno', 'tipoCombustible', 'usuario']);

        if ($request->filled('fecha_desde')) {
            $query->whereDate('created_at', '>=', $request->input('fecha_desde'));
        }

        if ($request->filled('fecha_hasta')) {
            $query->whereDate('created_at', '<=', $request->input('fecha_hasta'));
        }

        if ($request->filled('id_turno')) {
            $query->where('id_turno', (int) $request->input('id_turno'));
        }

        if ($request->filled('id_usuario')) {
            $query->where('id_usuario', (int) $request->input('id_usuario'));
        }

        $items = $query->orderByDesc('id')->get();
        $totalDiferencias = (float) $items->sum('total');
        $turnos = Turno::orderBy('id_turno')->get();
        $usuarios = User::orderBy('id_usuario')->get();

        return view('diferencias.index', compact('items', 'totalDiferencias', 'turnos', 'usuarios'));
    }

    public function create()
    {
        $turnos = Turno::orderBy('id_turno')->get();
        $tipos = TipoCombustible::orderBy('nombre')->get();

        return view('diferencias.create', compact('turnos', 'tipos'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'fecha' => 'required|date',
            'observacion' => 'nullable|string|max:1000',
            'id_turno' => 'required|integer|exists:turnos,id_turno',
            'id_tipo_combustible' => 'required|integer|exists:tipos_combustible,id_tipo_combustible',
            'cantidad_galones' => 'required|numeric|min:0',
            'precio' => 'nullable|numeric|min:0',
            'total' => 'nullable|numeric|min:0',
            'estado' => 'nullable|integer|in:0,1',
        ]);

        $data['estado'] = (int) ($data['estado'] ?? 1);
        $fecha = Carbon::parse($data['fecha'])->toDateString();
        $data['id_usuario'] = (int) auth()->id();

        $precio = $request->filled('precio')
            ? (float) $request->input('precio')
            : $this->obtenerPrecioPorTurno((int) $data['id_tipo_combustible'], (int) $data['id_turno'], $fecha);
        $total = $request->filled('total')
            ? (float) $request->input('total')
            : round(((float) $data['cantidad_galones']) * $precio, 2);

        $data['precio'] = round($precio, 2);
        $data['total'] = round($total, 2);

        $data['created_at'] = Carbon::parse($fecha)->setTime(now()->hour, now()->minute, now()->second);
        $data['updated_at'] = $data['created_at'];

        Diferencia::create($data);

        return redirect()->route('diferencias.index')->with('success', 'Diferencia creada.');
    }

    public function edit(string $id)
    {
        $item = Diferencia::findOrFail($id);
        $turnos = Turno::orderBy('id_turno')->get();
        $tipos = TipoCombustible::orderBy('nombre')->get();

        return view('diferencias.edit', compact('item', 'turnos', 'tipos'));
    }

    public function update(Request $request, string $id)
    {
        $item = Diferencia::findOrFail($id);

        $data = $request->validate([
            'fecha' => 'required|date',
            'observacion' => 'nullable|string|max:1000',
            'id_turno' => 'required|integer|exists:turnos,id_turno',
            'id_tipo_combustible' => 'required|integer|exists:tipos_combustible,id_tipo_combustible',
            'cantidad_galones' => 'required|numeric|min:0',
            'precio' => 'nullable|numeric|min:0',
            'total' => 'nullable|numeric|min:0',
            'estado' => 'required|integer|in:0,1',
        ]);

        $fecha = Carbon::parse($data['fecha'])->toDateString();

        $precio = $request->filled('precio')
            ? (float) $request->input('precio')
            : $this->obtenerPrecioPorTurno((int) $data['id_tipo_combustible'], (int) $data['id_turno'], $fecha);
        $total = $request->filled('total')
            ? (float) $request->input('total')
            : round(((float) $data['cantidad_galones']) * $precio, 2);

        $data['precio'] = round($precio, 2);
        $data['total'] = round($total, 2);

        $data['created_at'] = Carbon::parse($fecha)->setTime(
            (int) optional($item->created_at)->format('H'),
            (int) optional($item->created_at)->format('i'),
            (int) optional($item->created_at)->format('s')
        );
        $data['updated_at'] = now();

        $item->update($data);

        return redirect()->route('diferencias.index')->with('success', 'Diferencia actualizada.');
    }

    public function destroy(string $id)
    {
        $item = Diferencia::findOrFail($id);
        $item->delete();

        return redirect()->route('diferencias.index')->with('success', 'Diferencia eliminada.');
    }

    private function obtenerPrecioPorTurno(int $idTipoCombustible, int $idTurno, string $fecha): float
    {
        $precioDia = PrecioDia::where('tipo_combustible', $idTipoCombustible)
            ->whereDate('fecha', $fecha)
            ->orderByDesc('id')
            ->first();

        if (!$precioDia) {
            $precioDia = PrecioDia::where('tipo_combustible', $idTipoCombustible)
                ->whereDate('fecha', '<=', $fecha)
                ->orderByDesc('fecha')
                ->orderByDesc('id')
                ->first();
        }

        if (!$precioDia) {
            $precioDia = PrecioDia::where('tipo_combustible', $idTipoCombustible)
                ->orderByDesc('fecha')
                ->orderByDesc('id')
                ->first();
        }

        if (!$precioDia) {
            $tipoCombustible = TipoCombustible::find($idTipoCombustible);

            return (float) ($tipoCombustible?->precio ?? 0.0);
        }

        $turno = Turno::find($idTurno);
        $turnoNombre = mb_strtolower((string) ($turno?->turnos ?? $turno?->nombre ?? ''));

        if (str_contains($turnoNombre, 'mañ') || str_contains($turnoNombre, 'mana') || str_contains($turnoNombre, 'morning')) {
            return (float) ($precioDia->precio_turno_manana ?? 0);
        }

        if (str_contains($turnoNombre, 'tarde') || str_contains($turnoNombre, 'afternoon')) {
            return (float) ($precioDia->precio_turno_tarde ?? 0);
        }

        if (str_contains($turnoNombre, 'noche') || str_contains($turnoNombre, 'night')) {
            return (float) ($precioDia->precio_turno_noche ?? 0);
        }

        return (float) ($precioDia->precio_turno_manana ?? 0);
    }
}
