import { useMemo, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  ActionIcon,
  Badge,
  Button,
  Card,
  Center,
  Container,
  Group,
  Loader,
  NumberInput,
  Radio,
  Select,
  SimpleGrid,
  Stack,
  Table,
  Tabs,
  Text,
  Timeline,
  Title,
} from "@mantine/core";
import {
  ArrowLeft,
  Fuel,
  Gauge,
  History,
  Route,
  Truck,
  User,
  Wrench,
} from "lucide-react";

import { api } from "@/auth/http";
import { api as apiClient2 } from "@/services/api";
import { useToast } from "@/hooks/use-toast";
import {
  vehiclesService,
  type SaveVehiclePayload,
  type Vehicle,
} from "@/services/vehicles.service";
import { driversService } from "@/services/drivers.service";
import { fleetHistoryService } from "@/services/fleet-history.service";

interface MaintenanceCost {
  id: string;
  incurredDate: string;
  costAmount: number;
  costType: string;
  description?: string | null;
  serviceProvider?: string | null;
  invoiceNumber?: string | null;
}
interface FuelPurchase {
  id: string;
  purchaseDate: string;
  liters: number;
  costPerLiter: number;
  totalCost: number;
  fuelStation?: string | null;
  odometerReading?: number | null;
}
interface MileRecord {
  id: string;
  status: string;
  exactKm?: number | null;
  estimatedKm?: number | null;
  remainingPayment?: number | null;
  advancedPayment?: number | null;
  booking?: { reference?: string } | null;
  bookingId: string;
}

const fmtDate = (iso?: string | null) => {
  if (!iso) return "—";
  const d = new Date(iso);
  return Number.isNaN(d.getTime()) ? "—" : d.toLocaleDateString();
};
const fmtDateTime = (iso?: string | null) => {
  if (!iso) return "—";
  const d = new Date(iso);
  return Number.isNaN(d.getTime()) ? "—" : d.toLocaleString();
};
const money = (n?: number | null) =>
  n == null ? "—" : `ETB ${Number(n).toLocaleString(undefined, { maximumFractionDigits: 2 })}`;

const InfoRow = ({ label, value }: { label: string; value: React.ReactNode }) => (
  <Group justify="space-between" wrap="nowrap">
    <Text size="xs" c="dimmed" tt="uppercase">{label}</Text>
    <Text size="sm" fw={500} ta="right">{value}</Text>
  </Group>
);

const Loading = () => (
  <Center py="xl"><Loader size="sm" /></Center>
);

const VehicleDetailPage = () => {
  const { id = "" } = useParams<{ id: string }>();
  const navigate = useNavigate();

  const { data: vehicle, isLoading } = useQuery({
    queryKey: ["vehicle", id],
    queryFn: () => vehiclesService.getById(id).then((r) => r.data),
    enabled: Boolean(id),
  });

  const plate = vehicle
    ? [vehicle.code, vehicle.plateNumber].filter(Boolean).join(" · ")
    : "";

  return (
    <Container size="xl" py="xl" px="lg">
      <Group gap="sm" mb="md" wrap="nowrap">
        <ActionIcon variant="subtle" onClick={() => navigate("/dashboard/vehicles")} aria-label="Back">
          <ArrowLeft size={18} />
        </ActionIcon>
        <Truck size={22} />
        <Stack gap={0}>
          <Title order={4}>{plate || "Vehicle"}</Title>
          {vehicle && (
            <Group gap="xs">
              <Badge size="sm" variant="light">{vehicle.status}</Badge>
              <Badge size="sm" variant="light" color={vehicle.availability === "FREE" ? "green" : "orange"}>
                {vehicle.availability}
              </Badge>
              {vehicle.vehicleType && <Text size="xs" c="dimmed">{vehicle.vehicleType}</Text>}
            </Group>
          )}
        </Stack>
      </Group>

      {isLoading ? (
        <Loading />
      ) : !vehicle ? (
        <Text c="dimmed">Vehicle not found.</Text>
      ) : (
        <Tabs defaultValue="overview">
          <Tabs.List>
            <Tabs.Tab value="overview" leftSection={<Truck size={14} />}>Overview</Tabs.Tab>
            <Tabs.Tab value="driver" leftSection={<User size={14} />}>Driver</Tabs.Tab>
            <Tabs.Tab value="history" leftSection={<History size={14} />}>History</Tabs.Tab>
            <Tabs.Tab value="maintenance" leftSection={<Wrench size={14} />}>Maintenance</Tabs.Tab>
            <Tabs.Tab value="fuel" leftSection={<Fuel size={14} />}>Fuel</Tabs.Tab>
            <Tabs.Tab value="operations" leftSection={<Gauge size={14} />}>Operations</Tabs.Tab>
            <Tabs.Tab value="mile" leftSection={<Route size={14} />}>First/Last mile</Tabs.Tab>
          </Tabs.List>

          <Tabs.Panel value="overview" pt="lg">
            <Card withBorder radius="md" padding="md">
              <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
                <InfoRow label="Plate" value={vehicle.plateNumber ?? "—"} />
                <InfoRow label="Code" value={vehicle.code ?? "—"} />
                <InfoRow label="Registration" value={vehicle.registrationNumber ?? "—"} />
                <InfoRow label="Type" value={vehicle.vehicleType ?? "—"} />
                <InfoRow label="VIN" value={vehicle.vin ?? "—"} />
                <InfoRow label="Ownership" value={vehicle.ownership ?? "—"} />
                <InfoRow label="Manufacturer" value={vehicle.manufacturer ?? "—"} />
                <InfoRow label="Model" value={vehicle.model ?? "—"} />
                <InfoRow label="Year" value={vehicle.year ?? "—"} />
                <InfoRow label="Fuel type" value={vehicle.fuelType ?? "—"} />
                <InfoRow label="Capacity" value={vehicle.capacity ?? "—"} />
                <InfoRow label="Power plate" value={vehicle.powerPlateNo ?? "—"} />
                <InfoRow label="Trailer plate" value={vehicle.trailerPlateNo ?? "—"} />
                <InfoRow label="Status" value={vehicle.status ?? "—"} />
                <InfoRow label="Availability" value={vehicle.availability ?? "—"} />
                <InfoRow label="Assigned driver" value={vehicle.assignedDriverName ?? "—"} />
              </SimpleGrid>
            </Card>
          </Tabs.Panel>

          <Tabs.Panel value="driver" pt="lg">
            <DriverTab vehicleId={id} driverId={vehicle.assignedDriverId} fallbackName={vehicle.assignedDriverName} />
          </Tabs.Panel>

          <Tabs.Panel value="history" pt="lg">
            <HistoryTab vehicleId={id} />
          </Tabs.Panel>

          <Tabs.Panel value="maintenance" pt="lg">
            <MaintenanceTab vehicleId={id} />
          </Tabs.Panel>

          <Tabs.Panel value="fuel" pt="lg">
            <FuelTab vehicleId={id} />
          </Tabs.Panel>

          <Tabs.Panel value="operations" pt="lg">
            <OperationsTab vehicle={vehicle} />
          </Tabs.Panel>

          <Tabs.Panel value="mile" pt="lg">
            <MileTab vehicleId={id} />
          </Tabs.Panel>
        </Tabs>
      )}
    </Container>
  );
};

/**
 * Where a truck is and what it costs to run are per-trip operational facts, not
 * part of registering the vehicle — so they are edited here rather than on the
 * Add Vehicle form. `pricePerKm` is live billing input: first/last-mile charges
 * are `distance × pricePerKm`.
 */
const OperationsTab = ({ vehicle }: { vehicle: Vehicle }) => {
  const { toast } = useToast();
  const queryClient = useQueryClient();
  const [form, setForm] = useState({
    locationId: vehicle.locationId ?? "",
    estimatedDistanceKm: vehicle.estimatedDistanceKm ?? "",
    actualDistanceKm: vehicle.actualDistanceKm ?? "",
    pricePerKm: vehicle.pricePerKm ?? "",
    currency: vehicle.currency ?? "ETB",
  });

  const { data: yards = [], isLoading: yardsLoading } = useQuery(
    apiClient2.routes.yards.queryOptions(),
  );

  const save = useMutation({
    mutationFn: () =>
      vehiclesService.update(vehicle.id, {
        locationId: form.locationId || null,
        // Empty means "not recorded" — send null so the column is unset rather
        // than coerced to 0, which would read as a real measurement.
        estimatedDistanceKm: form.estimatedDistanceKm === "" ? null : Number(form.estimatedDistanceKm),
        actualDistanceKm: form.actualDistanceKm === "" ? null : Number(form.actualDistanceKm),
        pricePerKm: form.pricePerKm === "" ? null : Number(form.pricePerKm),
        currency: form.currency || null,
      } as Partial<SaveVehiclePayload> & { locationId?: string | null }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["vehicle", vehicle.id] });
      toast({ title: "Operational details saved" });
    },
    onError: () =>
      toast({ title: "Could not save operational details", variant: "destructive" }),
  });

  return (
    <Card withBorder radius="md" padding="md">
      <Stack gap="md">
        <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
          <Select
            label="Location"
            placeholder={yardsLoading ? "Loading yards..." : "Not set"}
            data={(yards as Array<{ id: string; label?: string; code?: string }>).map((y) => ({
              value: y.id,
              label: y.label ?? y.code ?? y.id,
            }))}
            value={form.locationId || null}
            onChange={(v) => setForm((f) => ({ ...f, locationId: v ?? "" }))}
            disabled={yardsLoading}
            searchable
            clearable
          />
          <NumberInput
            label="Price per KM"
            description="Used for first/last-mile billing"
            value={form.pricePerKm}
            onChange={(v) => setForm((f) => ({ ...f, pricePerKm: v as number | "" }))}
            min={0}
          />
          <NumberInput
            label="Estimated Distance (KM)"
            value={form.estimatedDistanceKm}
            onChange={(v) => setForm((f) => ({ ...f, estimatedDistanceKm: v as number | "" }))}
            min={0}
          />
          <NumberInput
            label="Actual Distance (KM)"
            value={form.actualDistanceKm}
            onChange={(v) => setForm((f) => ({ ...f, actualDistanceKm: v as number | "" }))}
            min={0}
          />
          <Radio.Group
            label="Currency"
            value={form.currency}
            onChange={(v) => setForm((f) => ({ ...f, currency: v }))}
          >
            <Group gap="lg" mt={6}>
              <Radio value="ETB" label="ETB" />
              <Radio value="USD" label="USD" />
            </Group>
          </Radio.Group>
        </SimpleGrid>
        <Group justify="flex-end">
          <Button onClick={() => save.mutate()} loading={save.isPending}>
            Save
          </Button>
        </Group>
      </Stack>
    </Card>
  );
};

const DriverTab = ({
  vehicleId,
  driverId,
  fallbackName,
}: {
  vehicleId: string;
  driverId?: string | null;
  fallbackName?: string | null;
}) => {
  const { data: driver } = useQuery({
    queryKey: ["driver", driverId],
    queryFn: () => driversService.getById(driverId!).then((r) => r.data),
    enabled: Boolean(driverId),
  });
  // All drivers that have driven this vehicle, from the assignment history.
  const { data: history = [], isLoading } = useQuery({
    queryKey: ["vehicle-history", vehicleId],
    queryFn: () => fleetHistoryService.vehicle(vehicleId),
  });
  const drivers = history
    .filter((e) => e.eventType === "DRIVER_ASSIGNED")
    .map((e) => ({
      id: e.id,
      driverId: e.driverId,
      name: (typeof e.metadata?.driverName === "string" && e.metadata.driverName) || e.label || "Driver",
      at: e.createdAt,
    }));

  return (
    <Stack gap="lg">
      {driverId && driver ? (
        <Card withBorder radius="md" padding="md">
          <Text size="sm" fw={600} mb="sm">Current driver</Text>
          <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
            <InfoRow label="Name" value={`${driver.firstName ?? ""} ${driver.lastName ?? ""}`.trim() || "—"} />
            <InfoRow label="Phone" value={driver.phoneNumber ?? "—"} />
            <InfoRow label="Email" value={driver.email ?? "—"} />
            <InfoRow label="License no." value={driver.licenseNumber ?? "—"} />
            <InfoRow label="License expiry" value={fmtDate(driver.licenseExpiryDate)} />
            <InfoRow label="Status" value={driver.status ?? "—"} />
          </SimpleGrid>
        </Card>
      ) : (
        <Text c="dimmed">{fallbackName ? `Assigned: ${fallbackName}` : "No driver currently assigned."}</Text>
      )}

      <Stack gap={4}>
        <Text size="sm" fw={600}>Driver history ({drivers.length})</Text>
        {isLoading ? (
          <Loading />
        ) : drivers.length === 0 ? (
          <Text size="sm" c="dimmed">No driver assignments recorded.</Text>
        ) : (
          <Table striped highlightOnHover>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Driver</Table.Th><Table.Th>Assigned</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {drivers.map((d) => (
                <Table.Tr key={d.id}>
                  <Table.Td>{d.name}</Table.Td>
                  <Table.Td>{fmtDateTime(d.at)}</Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        )}
      </Stack>
    </Stack>
  );
};

const HistoryTab = ({ vehicleId }: { vehicleId: string }) => {
  const { data = [], isLoading } = useQuery({
    queryKey: ["vehicle-history", vehicleId],
    queryFn: () => fleetHistoryService.vehicle(vehicleId),
  });
  if (isLoading) return <Loading />;
  if (!data.length) return <Text c="dimmed">No activity recorded yet.</Text>;
  return (
    <Timeline active={data.length} bulletSize={18} lineWidth={2}>
      {data.map((e) => (
        <Timeline.Item key={e.id} title={<Text size="sm" fw={500}>{e.eventType.replaceAll("_", " ")}</Text>}>
          {(e.label || e.fromValue || e.toValue) && (
            <Text size="xs" c="dimmed">
              {[e.label, e.fromValue && e.toValue ? `${e.fromValue} → ${e.toValue}` : e.toValue]
                .filter(Boolean)
                .join(" · ")}
            </Text>
          )}
          <Text size="xs" c="dimmed" mt={2}>{fmtDateTime(e.createdAt)}</Text>
        </Timeline.Item>
      ))}
    </Timeline>
  );
};

const MaintenanceTab = ({ vehicleId }: { vehicleId: string }) => {
  const { data = [], isLoading } = useQuery({
    queryKey: ["vehicle-maintenance", vehicleId],
    queryFn: () => api.get<MaintenanceCost[]>(`/maintenance/history/${vehicleId}`).then((r) => r.data),
  });
  const total = useMemo(() => data.reduce((s, m) => s + (Number(m.costAmount) || 0), 0), [data]);
  if (isLoading) return <Loading />;
  return (
    <Stack gap="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">Last 12 months</Text>
        <Text size="sm" fw={600}>Total: {money(total)}</Text>
      </Group>
      {data.length === 0 ? (
        <Text c="dimmed">No maintenance records.</Text>
      ) : (
        <Table.ScrollContainer minWidth={600}>
          <Table striped highlightOnHover>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Date</Table.Th><Table.Th>Type</Table.Th><Table.Th>Amount</Table.Th>
                <Table.Th>Description</Table.Th><Table.Th>Provider</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {data.map((m) => (
                <Table.Tr key={m.id}>
                  <Table.Td>{fmtDate(m.incurredDate)}</Table.Td>
                  <Table.Td><Badge size="sm" variant="light">{m.costType}</Badge></Table.Td>
                  <Table.Td>{money(m.costAmount)}</Table.Td>
                  <Table.Td>{m.description ?? "—"}</Table.Td>
                  <Table.Td>{m.serviceProvider ?? "—"}</Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </Stack>
  );
};

const FuelTab = ({ vehicleId }: { vehicleId: string }) => {
  const { data = [], isLoading } = useQuery({
    queryKey: ["vehicle-fuel", vehicleId],
    queryFn: () => {
      const end = new Date();
      const start = new Date();
      start.setMonth(start.getMonth() - 12);
      const qs = `startDate=${start.toISOString()}&endDate=${end.toISOString()}`;
      return api.get<FuelPurchase[]>(`/fuel/purchases/${vehicleId}?${qs}`).then((r) => r.data);
    },
  });
  const totals = useMemo(
    () => ({
      liters: data.reduce((s, f) => s + (Number(f.liters) || 0), 0),
      cost: data.reduce((s, f) => s + (Number(f.totalCost) || 0), 0),
    }),
    [data],
  );
  if (isLoading) return <Loading />;
  return (
    <Stack gap="sm">
      <SimpleGrid cols={{ base: 2, sm: 3 }} spacing="sm">
        <Card withBorder radius="md" padding="sm">
          <Text size="xs" c="dimmed">Total litres</Text>
          <Text fw={700}>{totals.liters.toLocaleString(undefined, { maximumFractionDigits: 1 })} L</Text>
        </Card>
        <Card withBorder radius="md" padding="sm">
          <Text size="xs" c="dimmed">Total fuel cost</Text>
          <Text fw={700}>{money(totals.cost)}</Text>
        </Card>
        <Card withBorder radius="md" padding="sm">
          <Text size="xs" c="dimmed">Purchases</Text>
          <Text fw={700}>{data.length}</Text>
        </Card>
      </SimpleGrid>
      {data.length === 0 ? (
        <Text c="dimmed">No fuel purchases in the last 12 months.</Text>
      ) : (
        <Table.ScrollContainer minWidth={640}>
          <Table striped highlightOnHover>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Date</Table.Th><Table.Th>Litres</Table.Th><Table.Th>Cost/L</Table.Th>
                <Table.Th>Total</Table.Th><Table.Th>Odometer</Table.Th><Table.Th>Station</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {data.map((f) => (
                <Table.Tr key={f.id}>
                  <Table.Td>{fmtDate(f.purchaseDate)}</Table.Td>
                  <Table.Td>{f.liters} L</Table.Td>
                  <Table.Td>{money(f.costPerLiter)}</Table.Td>
                  <Table.Td>{money(f.totalCost)}</Table.Td>
                  <Table.Td>{f.odometerReading ?? "—"}</Table.Td>
                  <Table.Td>{f.fuelStation ?? "—"}</Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </Stack>
  );
};

const mileTotal = (rows: MileRecord[]) =>
  rows.reduce((s, r) => s + (Number(r.remainingPayment) || 0), 0);

const MileTable = ({ title, rows }: { title: string; rows: MileRecord[] }) => (
  <Stack gap={4}>
    <Group justify="space-between">
      <Text size="sm" fw={600}>{title} ({rows.length})</Text>
      <Text size="sm" fw={600}>Total: {money(mileTotal(rows))}</Text>
    </Group>
    {rows.length === 0 ? (
      <Text size="sm" c="dimmed">None.</Text>
    ) : (
      <Table striped>
        <Table.Thead>
          <Table.Tr>
            <Table.Th>Booking</Table.Th><Table.Th>Status</Table.Th>
            <Table.Th>Distance (km)</Table.Th><Table.Th>Cost</Table.Th>
          </Table.Tr>
        </Table.Thead>
        <Table.Tbody>
          {rows.map((r) => (
            <Table.Tr key={r.id}>
              <Table.Td>{r.booking?.reference ?? r.bookingId}</Table.Td>
              <Table.Td><Badge size="sm" variant="light">{r.status}</Badge></Table.Td>
              <Table.Td>{r.exactKm ?? r.estimatedKm ?? "—"}</Table.Td>
              <Table.Td>{money(r.remainingPayment)}</Table.Td>
            </Table.Tr>
          ))}
        </Table.Tbody>
      </Table>
    )}
  </Stack>
);

const MileTab = ({ vehicleId }: { vehicleId: string }) => {
  const first = useQuery({
    queryKey: ["vehicle-first-mile", vehicleId],
    queryFn: () =>
      api.get<{ data: MileRecord[] }>(`/first-mile?vehicleId=${vehicleId}&pageSize=1000`).then((r) => r.data.data ?? []),
  });
  const last = useQuery({
    queryKey: ["vehicle-last-mile", vehicleId],
    queryFn: () =>
      api.get<{ data: MileRecord[] }>(`/last-mile?vehicleId=${vehicleId}&pageSize=1000`).then((r) => r.data.data ?? []),
  });
  if (first.isLoading || last.isLoading) return <Loading />;
  const firstRows = first.data ?? [];
  const lastRows = last.data ?? [];
  const grandTotal = mileTotal(firstRows) + mileTotal(lastRows);
  return (
    <Stack gap="lg">
      <Card withBorder radius="md" padding="sm">
        <Group justify="space-between">
          <Text size="sm" c="dimmed">Total first + last mile revenue for this vehicle</Text>
          <Text fw={700}>{money(grandTotal)}</Text>
        </Group>
      </Card>
      <MileTable title="First-mile" rows={firstRows} />
      <MileTable title="Last-mile" rows={lastRows} />
    </Stack>
  );
};

export default VehicleDetailPage;
