import { FastifyInstance } from "fastify";
import prisma from "../../config/database";
import { requireAnyPermission, requirePermission } from "../../middleware/auth";
import { logAudit } from "../../services/audit";
import { success, error, parseId } from "../../utils/response";
import { parseBody } from "../../schemas/common";
import {
  CreateVehicleSchema,
  UpdateVehicleSchema,
} from "../../schemas/vehicles.schema";

export default async function vehiclesRoutes(
  fastify: FastifyInstance,
): Promise<void> {
  // Read is consumed both by the Vehicles management page (vehicles.manage)
  // and by the trip-recording/history pages (trips.*), which pick a vehicle
  // without holding vehicles.manage. Allow any of those — but no longer a
  // bare authenticated user (that was an information-disclosure gap).
  fastify.get(
    "/",
    {
      preHandler: requireAnyPermission(
        "vehicles.manage",
        "trips.record",
        "trips.manage",
        "trips.history",
      ),
    },
    async (_request, reply) => {
      const vehicles = await prisma.vehicles.findMany({
        orderBy: { name: "asc" },
      });

      // Compute current_km and trip_count from trips table
      const tripStats = await prisma.trips.groupBy({
        by: ["vehicle_id"],
        _max: { end_km: true },
        _count: { id: true },
      });
      const statsMap = new Map(
        tripStats.map((s) => [
          s.vehicle_id,
          { maxKm: s._max.end_km ?? 0, count: s._count.id },
        ]),
      );

      const enriched = vehicles.map((v) => {
        const stats = statsMap.get(v.id);
        return {
          ...v,
          current_km: stats
            ? Math.max(v.initial_km, stats.maxKm)
            : v.initial_km,
          trip_count: stats?.count ?? 0,
        };
      });

      return success(reply, enriched);
    },
  );

  fastify.post(
    "/",
    { preHandler: requirePermission("vehicles.manage") },
    async (request, reply) => {
      const parsed = parseBody(CreateVehicleSchema, request.body);
      if ("error" in parsed) return error(reply, parsed.error, 400);
      const body = parsed.data;
      const vehicle = await prisma.vehicles.create({
        data: {
          spz: body.spz,
          name: body.name,
          brand: body.brand ?? null,
          model: body.model ?? null,
          initial_km: body.initial_km,
          actual_km: body.actual_km,
          is_active: body.is_active !== false,
        },
      });

      await logAudit({
        request,
        authData: request.authData,
        action: "create",
        entityType: "vehicle",
        entityId: vehicle.id,
        description: `Vytvořeno vozidlo ${vehicle.name}`,
      });
      return success(reply, { id: vehicle.id }, 201, "Vozidlo bylo vytvořeno");
    },
  );

  fastify.put<{ Params: { id: string } }>(
    "/:id",
    { preHandler: requirePermission("vehicles.manage") },
    async (request, reply) => {
      const id = parseId(request.params.id, reply);
      if (id === null) return;
      const parsed = parseBody(UpdateVehicleSchema, request.body);
      if ("error" in parsed) return error(reply, parsed.error, 400);
      const body = parsed.data;
      const existing = await prisma.vehicles.findUnique({ where: { id } });
      if (!existing) return error(reply, "Vozidlo nenalezeno", 404);

      await prisma.vehicles.update({
        where: { id },
        data: {
          spz: body.spz !== undefined ? String(body.spz) : undefined,
          name: body.name !== undefined ? String(body.name) : undefined,
          brand:
            body.brand !== undefined
              ? body.brand
                ? String(body.brand)
                : null
              : undefined,
          model:
            body.model !== undefined
              ? body.model
                ? String(body.model)
                : null
              : undefined,
          initial_km:
            body.initial_km !== undefined ? Number(body.initial_km) : undefined,
          actual_km:
            body.actual_km !== undefined ? Number(body.actual_km) : undefined,
          is_active:
            body.is_active !== undefined ? !!body.is_active : undefined,
        },
      });
      await logAudit({
        request,
        authData: request.authData,
        action: "update",
        entityType: "vehicle",
        entityId: id,
        description: `Upraveno vozidlo ${existing.name}`,
      });
      return success(reply, { id }, 200, "Vozidlo bylo uloženo");
    },
  );

  fastify.delete<{ Params: { id: string } }>(
    "/:id",
    { preHandler: requirePermission("vehicles.manage") },
    async (request, reply) => {
      const id = parseId(request.params.id, reply);
      if (id === null) return;
      const existing = await prisma.vehicles.findUnique({ where: { id } });
      if (!existing) return error(reply, "Vozidlo nenalezeno", 404);

      // Check for linked trips before deleting
      const tripCount = await prisma.trips.count({
        where: { vehicle_id: id },
      });
      if (tripCount > 0) {
        return error(
          reply,
          "Vozidlo má přiřazené jízdy a nelze jej smazat",
          409,
        );
      }

      await prisma.vehicles.delete({ where: { id } });
      await logAudit({
        request,
        authData: request.authData,
        action: "delete",
        entityType: "vehicle",
        entityId: id,
        description: `Smazáno vozidlo ${existing.name}`,
      });
      return success(reply, null, 200, "Vozidlo smazáno");
    },
  );
}
