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,
  SimpleGrid,
  Stack,
  Table,
  Tabs,
  Text,
  Timeline,
  Title,
} from "@mantine/core";
import { SmartFileInput } from "@edr/ui-common";
import type { IFileUploadSetting } from "@edr/types/freight";
import {
  ArrowLeft,
  Download,
  Eye,
  FileText,
  History,
  Route,
  ShieldCheck,
  Trash2,
  Upload,
  Truck,
  User,
} from "lucide-react";

import { driversService } from "@/services/drivers.service";
import { vehiclesService } from "@/services/vehicles.service";
import { fleetHistoryService, type FleetHistoryEvent } from "@/services/fleet-history.service";
import { fileUploadSettingsService } from "@/services/fileUploadSettings.service";
import {
  downloadBookingFile,
  fetchViewableFile,
} from "@/services/files.service";
import { useToast } from "@/hooks/use-toast";

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 meta = (e: FleetHistoryEvent, k: string) => {
  const v = e.metadata?.[k];
  return typeof v === "string" && v ? v : null;
};

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 fmtSize = (bytes: number) => {
  if (!bytes) return "—";
  const kb = bytes / 1024;
  return kb < 1024 ? `${kb.toFixed(0)} KB` : `${(kb / 1024).toFixed(1)} MB`;
};

/** Upload-area setting code configured on the File Settings page. */
const DRIVER_DOCS_CODE = "driver_docs";
// Field key the FALLBACK setting is keyed on (used only when the "driver_docs"
// upload area hasn't been configured in File Settings yet).
const DRIVER_DOCS_KEY = "driver_docs";
/** Fallback single-field setting so the dropzone still works before an admin
 *  configures the "driver_docs" area in File Settings. */
const DRIVER_DOCS_FALLBACK: IFileUploadSetting = {
  id: "driver-docs-setting",
  createdAt: "",
  updatedAt: "",
  deletedAt: null,
  code: "driver_docs",
  label: "Driver documents",
  description: null,
  entity: "other",
  fields: [
    {
      id: "driver-docs-field",
      createdAt: "",
      updatedAt: "",
      deletedAt: null,
      settingId: "driver-docs-setting",
      fileKey: DRIVER_DOCS_KEY,
      fileLabel: "Upload driver document(s)",
      helpText: "License, national ID, contracts, training certificates, etc.",
      isRequired: false,
      isMultiple: true,
      maxFiles: 20,
      allowedExtensions: ["pdf", "png", "jpg", "jpeg", "doc", "docx"],
      maxSizeMb: 10,
      order: 1,
    },
  ],
};

/** Driver documents upload + view area (files stored under code "driver_docs"). */
const DriverDocuments = ({ driverId }: { driverId: string }) => {
  const { toast } = useToast();
  const qc = useQueryClient();
  // Files selected per configured field key (SmartFileInput is multi-field).
  const [selectedMap, setSelectedMap] = useState<Record<string, File | File[] | null>>({});
  const selectedFiles = Object.values(selectedMap).flatMap((v) =>
    Array.isArray(v) ? v : v ? [v] : [],
  );

  // Upload-area configuration from the File Settings page (code "driver_docs").
  // Falls back to a default field until an admin configures it there.
  const { data: setting } = useQuery({
    queryKey: ["file-upload-setting", DRIVER_DOCS_CODE],
    queryFn: () => fileUploadSettingsService.getByCode(DRIVER_DOCS_CODE),
    retry: false,
  });
  const activeSetting = setting ?? DRIVER_DOCS_FALLBACK;

  const { data: docs = [], isLoading } = useQuery({
    queryKey: ["driver", driverId, "documents"],
    queryFn: () => driversService.listDocuments(driverId).then((r) => r.data ?? []),
    enabled: Boolean(driverId),
  });

  const uploadMutation = useMutation({
    mutationFn: (files: File[]) => driversService.uploadDocuments(driverId, files),
    onSuccess: () => {
      toast({ title: "Documents uploaded" });
      void qc.invalidateQueries({ queryKey: ["driver", driverId, "documents"] });
    },
    onError: (err: unknown) => {
      const description =
        (err as { response?: { data?: { message?: string } } })?.response?.data?.message ??
        "Upload failed";
      toast({ title: "Upload failed", description, variant: "destructive" });
    },
  });

  const removeMutation = useMutation({
    mutationFn: (fileId: string) => driversService.removeDocument(driverId, fileId),
    onSuccess: () => {
      toast({ title: "Document deleted" });
      void qc.invalidateQueries({ queryKey: ["driver", driverId, "documents"] });
    },
    onError: () => toast({ title: "Delete failed", variant: "destructive" }),
  });

  return (
    <Card withBorder padding="lg" radius="md">
      <Stack gap="md" mb="lg">
        <Text fw={600} size="sm">{activeSetting.label ?? "Upload documents"}</Text>
        <SmartFileInput
          file={activeSetting}
          value={selectedMap}
          onChange={setSelectedMap}
        />
        <Group justify="flex-end">
          <Button
            size="xs"
            leftSection={<Upload size={14} />}
            loading={uploadMutation.isPending}
            disabled={selectedFiles.length === 0}
            onClick={() =>
              uploadMutation.mutate(selectedFiles, { onSuccess: () => setSelectedMap({}) })
            }
          >
            Upload {selectedFiles.length > 0 ? `(${selectedFiles.length})` : ""}
          </Button>
        </Group>
      </Stack>

      <Text fw={600} size="sm" mb="sm">Uploaded documents ({docs.length})</Text>
      {isLoading ? (
        <Loading />
      ) : docs.length === 0 ? (
        <Text c="dimmed" size="sm" ta="center" py="md">No documents uploaded yet.</Text>
      ) : (
        <Table highlightOnHover>
          <Table.Thead>
            <Table.Tr>
              <Table.Th>Name</Table.Th>
              <Table.Th>Size</Table.Th>
              <Table.Th>Uploaded</Table.Th>
              <Table.Th ta="right">Actions</Table.Th>
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {docs.map((doc) => (
              <Table.Tr key={doc.id}>
                <Table.Td>
                  <Group gap="xs" wrap="nowrap">
                    <FileText size={15} />
                    <Text size="sm" truncate>{doc.name}</Text>
                  </Group>
                </Table.Td>
                <Table.Td>{fmtSize(doc.size)}</Table.Td>
                <Table.Td>{fmtDate(doc.createdAt)}</Table.Td>
                <Table.Td>
                  <Group gap={4} justify="flex-end" wrap="nowrap">
                    <ActionIcon
                      variant="subtle"
                      aria-label="View"
                      onClick={() =>
                        void fetchViewableFile(doc.id, doc.name).then((f) =>
                          window.open(f.url, "_blank"),
                        )
                      }
                    >
                      <Eye size={16} />
                    </ActionIcon>
                    <ActionIcon
                      variant="subtle"
                      aria-label="Download"
                      onClick={() => void downloadBookingFile(doc.id, doc.name)}
                    >
                      <Download size={16} />
                    </ActionIcon>
                    <ActionIcon
                      variant="subtle"
                      color="red"
                      aria-label="Delete"
                      loading={removeMutation.isPending && removeMutation.variables === doc.id}
                      onClick={() => removeMutation.mutate(doc.id)}
                    >
                      <Trash2 size={16} />
                    </ActionIcon>
                  </Group>
                </Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>
      )}
    </Card>
  );
};

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

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

  const name = driver ? `${driver.firstName ?? ""} ${driver.lastName ?? ""}`.trim() : "";
  const licenseExpired =
    driver?.licenseExpiryDate && new Date(driver.licenseExpiryDate) < new Date();

  return (
    <Container size="xl" py="xl" px="lg">
      <Group gap="sm" mb="md" wrap="nowrap">
        <ActionIcon variant="subtle" onClick={() => navigate("/dashboard/drivers")} aria-label="Back">
          <ArrowLeft size={18} />
        </ActionIcon>
        <User size={22} />
        <Stack gap={0}>
          <Title order={4}>{name || "Driver"}</Title>
          {driver && (
            <Group gap="xs">
              <Badge size="sm" variant="light">{driver.status}</Badge>
              {driver.faydaVerified && (
                <Badge size="sm" variant="light" color="green" leftSection={<ShieldCheck size={12} />}>
                  Fayda verified
                </Badge>
              )}
              {licenseExpired && (
                <Badge size="sm" variant="light" color="red">License expired</Badge>
              )}
              <Text size="xs" c="dimmed">{driver.licenseNumber}</Text>
            </Group>
          )}
        </Stack>
      </Group>

      {isLoading ? (
        <Loading />
      ) : !driver ? (
        <Text c="dimmed">Driver not found.</Text>
      ) : (
        <Tabs defaultValue="overview">
          <Tabs.List>
            <Tabs.Tab value="overview" leftSection={<User size={14} />}>Overview</Tabs.Tab>
            <Tabs.Tab value="vehicles" leftSection={<Truck size={14} />}>Vehicles</Tabs.Tab>
            <Tabs.Tab value="history" leftSection={<History size={14} />}>History</Tabs.Tab>
            <Tabs.Tab value="trips" leftSection={<Route size={14} />}>Trips</Tabs.Tab>
            <Tabs.Tab value="documents" leftSection={<FileText size={14} />}>Documents</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="Name" value={name || "—"} />
                <InfoRow label="Phone" value={driver.phoneNumber ?? "—"} />
                <InfoRow label="Email" value={driver.email ?? "—"} />
                <InfoRow label="License no." value={driver.licenseNumber ?? "—"} />
                <InfoRow
                  label="License expiry"
                  value={
                    <Text size="sm" fw={500} c={licenseExpired ? "red" : undefined}>
                      {fmtDate(driver.licenseExpiryDate)}
                    </Text>
                  }
                />
                <InfoRow label="Date of birth" value={fmtDate(driver.dateOfBirth)} />
                <InfoRow label="Status" value={driver.status ?? "—"} />
                <InfoRow label="Fayda verified" value={driver.faydaVerified ? "Yes" : "No"} />
                <InfoRow
                  label="Authorized vehicles"
                  value={driver.vehicleTypesAuthorized?.join(", ") || "—"}
                />
                <InfoRow label="Total trips" value={driver.totalTrips ?? "—"} />
                <InfoRow label="Rating" value={driver.rating ?? "—"} />
                <InfoRow label="Address" value={driver.address ?? "—"} />
                <InfoRow label="Emergency contact" value={driver.emergencyContact ?? "—"} />
              </SimpleGrid>
            </Card>
          </Tabs.Panel>

          <Tabs.Panel value="vehicles" pt="lg">
            <VehiclesTab driverId={id} />
          </Tabs.Panel>

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

          <Tabs.Panel value="trips" pt="lg">
            <TripsTab driverId={id} />
          </Tabs.Panel>

          <Tabs.Panel value="documents" pt="lg">
            <DriverDocuments driverId={id} />
          </Tabs.Panel>
        </Tabs>
      )}
    </Container>
  );
};

const useDriverHistory = (driverId: string) =>
  useQuery({
    queryKey: ["driver-history", driverId],
    queryFn: () => fleetHistoryService.driver(driverId),
  });

/** id → "code · plate" map so events without a stored plate still show a name. */
const useVehicleMap = () => {
  const { data } = useQuery({
    queryKey: ["vehicles-all"],
    queryFn: () => vehiclesService.getAll({}).then((r) => r.data),
  });
  return useMemo(() => {
    const m = new Map<string, string>();
    for (const v of data ?? []) {
      m.set(v.id, [v.code, v.plateNumber].filter(Boolean).join(" · ") || v.id);
    }
    return m;
  }, [data]);
};

const VehiclesTab = ({ driverId }: { driverId: string }) => {
  const { data = [], isLoading } = useDriverHistory(driverId);
  const vmap = useVehicleMap();
  const rows = data
    .filter((e) => e.eventType === "DRIVER_ASSIGNED")
    .map((e) => ({
      id: e.id,
      plate: meta(e, "vehiclePlate") || (e.vehicleId ? vmap.get(e.vehicleId) : null) || "Vehicle",
      at: e.createdAt,
    }));
  if (isLoading) return <Loading />;
  return (
    <Stack gap={4}>
      <Text size="sm" fw={600}>Vehicles driven ({rows.length})</Text>
      {rows.length === 0 ? (
        <Text size="sm" c="dimmed">No vehicle assignments recorded.</Text>
      ) : (
        <Table striped highlightOnHover>
          <Table.Thead>
            <Table.Tr><Table.Th>Vehicle</Table.Th><Table.Th>Assigned</Table.Th></Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {rows.map((r) => (
              <Table.Tr key={r.id}>
                <Table.Td>{r.plate}</Table.Td>
                <Table.Td>{fmtDateTime(r.at)}</Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>
      )}
    </Stack>
  );
};

const HistoryTab = ({ driverId }: { driverId: string }) => {
  const { data = [], isLoading } = useDriverHistory(driverId);
  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>}>
          {(meta(e, "vehiclePlate") || meta(e, "bookingRef") || e.label) && (
            <Text size="xs" c="dimmed">
              {[meta(e, "vehiclePlate"), meta(e, "bookingRef") && `Booking ${meta(e, "bookingRef")}`, e.label]
                .filter(Boolean)
                .join(" · ")}
            </Text>
          )}
          <Text size="xs" c="dimmed" mt={2}>{fmtDateTime(e.createdAt)}</Text>
        </Timeline.Item>
      ))}
    </Timeline>
  );
};

const TripsTab = ({ driverId }: { driverId: string }) => {
  const { data = [], isLoading } = useDriverHistory(driverId);
  const vmap = useVehicleMap();
  const trips = useMemo(
    () =>
      data
        .filter((e) => e.eventType === "MILE_VEHICLE_ASSIGNED")
        .map((e) => ({
          id: e.id,
          mile: meta(e, "mile") === "LAST" ? "Last-mile" : "First-mile",
          booking: meta(e, "bookingRef") ?? "—",
          vehicle: meta(e, "vehiclePlate") || (e.vehicleId ? vmap.get(e.vehicleId) : null) || "—",
          status: e.label ?? "—",
          at: e.createdAt,
        })),
    [data, vmap],
  );
  if (isLoading) return <Loading />;
  return (
    <Stack gap={4}>
      <Text size="sm" fw={600}>Trips assigned ({trips.length})</Text>
      {trips.length === 0 ? (
        <Text size="sm" c="dimmed">No trips recorded.</Text>
      ) : (
        <Table.ScrollContainer minWidth={640}>
          <Table striped highlightOnHover>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Mile</Table.Th><Table.Th>Booking</Table.Th>
                <Table.Th>Vehicle</Table.Th><Table.Th>Status</Table.Th><Table.Th>When</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {trips.map((t) => (
                <Table.Tr key={t.id}>
                  <Table.Td><Badge size="sm" variant="light">{t.mile}</Badge></Table.Td>
                  <Table.Td>{t.booking}</Table.Td>
                  <Table.Td>{t.vehicle}</Table.Td>
                  <Table.Td>{t.status}</Table.Td>
                  <Table.Td>{fmtDateTime(t.at)}</Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </Stack>
  );
};

export default DriverDetailPage;
