import { useEffect, useState } from "react";
import {
  Badge,
  Box,
  Button,
  Card,
  Group,
  Modal,
  NumberInput,
  Stack,
  Text,
  Textarea,
} from "@mantine/core";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { ColumnDef } from "@edr/ui-common";
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";

import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { useToast } from "@/hooks/use-toast";
import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";
import {
  lastMileRequestsService,
  type LastMileRequest,
  type LastMileRequestStatus,
} from "@/services/last-mile-requests.service";

const STATUS_META: Record<LastMileRequestStatus, { label: string; color: string }> = {
  AWAITING_CONFIRMATION: { label: "Awaiting Confirmation", color: "gray" },
  SUBMITTED: { label: "Submitted", color: "yellow" },
  APPROVED: { label: "Approved", color: "green" },
  REJECTED: { label: "Rejected", color: "red" },
};

type StatusFilter = "ALL" | LastMileRequestStatus;

const FILTER_OPTIONS: { value: StatusFilter; label: string }[] = [
  { value: "SUBMITTED", label: "Submitted" },
  { value: "APPROVED", label: "Approved" },
  { value: "REJECTED", label: "Rejected" },
  { value: "AWAITING_CONFIRMATION", label: "Awaiting Confirmation" },
  { value: "ALL", label: "All" },
];

const fmtDate = (iso?: string | null) =>
  iso ? new Date(iso).toLocaleString("en-US", { dateStyle: "medium", timeStyle: "short" }) : "—";

export function LastMileRequestsPanel() {
  const { toast } = useToast();
  const qc = useQueryClient();
  const { user } = useAuth();
  const canApprove = hasPermission(user, FREIGHT_PERMS.lastMile.requestApprove);

  const [statusFilter, setStatusFilter] = useState<StatusFilter>("SUBMITTED");
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [approveTarget, setApproveTarget] = useState<LastMileRequest | null>(null);
  const [rejectTarget, setRejectTarget] = useState<LastMileRequest | null>(null);
  const [advanceAmount, setAdvanceAmount] = useState<number | string>("");
  const [rejectReason, setRejectReason] = useState("");

  const filter = {
    ...(statusFilter !== "ALL" ? { status: statusFilter } : {}),
    page: pagination.pageIndex + 1,
    pageSize: pagination.pageSize,
  };

  const { data, isLoading } = useQuery({
    queryKey: QUERY_KEYS.LAST_MILE_REQUESTS.list(filter),
    queryFn: async () => (await lastMileRequestsService.list(filter)).data,
  });
  const rows = data?.data ?? [];
  const meta = data?.meta;

  const { data: freeTrucks } = useQuery({
    queryKey: QUERY_KEYS.LAST_MILE_REQUESTS.freeTruckCount,
    queryFn: async () => (await lastMileRequestsService.freeTruckCount()).data,
  });

  // Rule-based estimate for the approve dialog (estimated km × live last-mile
  // rates). Prefills the advance once, without clobbering a typed value.
  const { data: estimate } = useQuery({
    queryKey: QUERY_KEYS.LAST_MILE_REQUESTS.priceEstimate(approveTarget?.id ?? ""),
    queryFn: async () =>
      (await lastMileRequestsService.priceEstimate(approveTarget!.id)).data,
    enabled: Boolean(approveTarget),
  });
  useEffect(() => {
    if (approveTarget && estimate?.total != null && advanceAmount === "") {
      setAdvanceAmount(estimate.total);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [estimate, approveTarget]);

  const invalidate = () =>
    qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE_REQUESTS.ROOT });

  const downloadContract = async (r: LastMileRequest) => {
    try {
      const { data: blob } = await lastMileRequestsService.contractDocument(r.id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `LM_${r.booking?.company?.name?.replace(/[^A-Za-z0-9._-]+/g, "_") ?? r.id}.pdf`;
      a.click();
      URL.revokeObjectURL(url);
    } catch {
      toast({ title: "Contract PDF not available", variant: "destructive" });
    }
  };

  const approve = useMutation({
    mutationFn: () =>
      lastMileRequestsService.approve(approveTarget!.id, Number(advanceAmount)),
    onSuccess: () => {
      void invalidate();
      toast({ title: "Request approved" });
      setApproveTarget(null);
      setAdvanceAmount("");
    },
    onError: (e: unknown) => {
      const description = (e as { response?: { data?: { message?: string } } })?.response?.data?.message;
      toast({ title: "Approve failed", description, variant: "destructive" });
    },
  });

  const reject = useMutation({
    mutationFn: () => lastMileRequestsService.reject(rejectTarget!.id, rejectReason.trim()),
    onSuccess: () => {
      void invalidate();
      toast({ title: "Request rejected" });
      setRejectTarget(null);
      setRejectReason("");
    },
    onError: (e: unknown) => {
      const description = (e as { response?: { data?: { message?: string } } })?.response?.data?.message;
      toast({ title: "Reject failed", description, variant: "destructive" });
    },
  });

  const columns: ColumnDef<LastMileRequest>[] = [
    {
      id: "booking",
      header: () => <span>Booking</span>,
      cell: ({ row }) => {
        const r = row.original;
        return (
          <Stack gap={0}>
            <Text size="sm" fw={600}>{r.booking?.reference ?? r.bookingId}</Text>
            <Text size="xs" c="dimmed">{r.booking?.company?.name ?? "—"}</Text>
          </Stack>
        );
      },
    },
    {
      id: "containers",
      header: () => <span>Requested Containers</span>,
      cell: ({ row }) => {
        const r = row.original;
        const nums = r.requestedContainerNumbers;
        return (
          <Stack gap={0}>
            <Text size="sm">{nums?.length ? nums.join(", ") : "—"}</Text>
            {r.requestedDeliveryDate && (
              <Text size="xs" c="dimmed">Delivery: {r.requestedDeliveryDate}</Text>
            )}
          </Stack>
        );
      },
    },
    {
      id: "submittedAt",
      header: () => <span>Submitted</span>,
      cell: ({ row }) => <Text size="sm">{fmtDate(row.original.submittedAt)}</Text>,
    },
    {
      id: "status",
      header: () => <span>Status</span>,
      cell: ({ row }) => {
        const meta = STATUS_META[row.original.status];
        return (
          <Badge color={meta.color} variant="light" size="sm">
            {meta.label}
          </Badge>
        );
      },
    },
    {
      id: "contract",
      header: () => <span>LM Contract</span>,
      cell: ({ row }) => {
        const r = row.original;
        if (r.status !== "APPROVED") return <Text size="sm" c="dimmed">—</Text>;
        return (
          <Stack gap={4} align="flex-start">
            <Badge color={r.customerSignedAt ? "green" : "yellow"} variant="light" size="sm">
              {r.customerSignedAt ? "Signed" : "Awaiting signature"}
            </Badge>
            <Button size="compact-xs" variant="subtle" onClick={() => void downloadContract(r)}>
              Download PDF
            </Button>
          </Stack>
        );
      },
    },
    ...(canApprove
      ? [
          {
            id: "actions",
            header: () => <span>Actions</span>,
            cell: ({ row }: { row: { original: LastMileRequest } }) => {
              const r = row.original;
              if (r.status !== "SUBMITTED") return null;
              return (
                <Group gap="xs">
                  <Button size="xs" variant="light" color="green" onClick={() => setApproveTarget(r)}>
                    Approve
                  </Button>
                  <Button size="xs" variant="light" color="red" onClick={() => setRejectTarget(r)}>
                    Reject
                  </Button>
                </Group>
              );
            },
          } as ColumnDef<LastMileRequest>,
        ]
      : []),
  ];

  return (
    <Card radius="lg" padding={0} withBorder style={{ borderColor: "var(--mantine-color-gray-2)" }}>
      <Stack gap={0}>
        <Box px="md" pt="md" pb="sm" w="100%">
          <Stack gap="sm">
            <Text size="sm" c="dimmed">
              {freeTrucks?.count ?? 0} truck{freeTrucks?.count === 1 ? "" : "s"} currently free
            </Text>
            <Group gap="xs" wrap="wrap">
              {FILTER_OPTIONS.map((option) => {
                const active = statusFilter === option.value;
                return (
                  <Button
                    key={option.value}
                    size="xs"
                    variant={active ? "filled" : "default"}
                    styles={{ label: { fontWeight: 500 } }}
                    onClick={() => {
                      setStatusFilter(option.value);
                      setPagination((p) => ({ ...p, pageIndex: 0 }));
                    }}
                  >
                    {option.label}
                  </Button>
                );
              })}
            </Group>
          </Stack>
        </Box>

        <DataTable
          columns={columns}
          data={rows}
          status={isLoading ? "loading" : "success"}
          emptyMessage="No last-mile confirmation requests found"
          pagination={{
            pageIndex: pagination.pageIndex,
            pageSize: pagination.pageSize,
            pageCount: meta?.totalPages ?? 1,
            totalCount: meta?.total ?? 0,
          }}
          tableOptions={{
            manualPagination: true,
            pageCount: meta?.totalPages ?? 1,
            state: { pagination },
            onPaginationChange: setPagination,
          }}
          containerClassName="border-0 shadow-none bg-transparent"
          footer={({ table, pagination: fp }) => (
            <DataTableFooter table={table} pagination={fp} options={{ labels: { items: "requests" } }} />
          )}
        />
      </Stack>

      <Modal
        opened={Boolean(approveTarget)}
        onClose={() => {
          setApproveTarget(null);
          setAdvanceAmount("");
        }}
        title={<Text fw={700}>Approve request{approveTarget?.booking?.reference ? ` · ${approveTarget.booking.reference}` : ""}</Text>}
        centered
      >
        <Stack gap="md">
          {estimate?.total != null && (
            <Stack gap={4}>
              {estimate.lines.map((line) => (
                <Text key={line.description} size="xs" c="dimmed">
                  {line.description} — {line.amount.toLocaleString()}
                </Text>
              ))}
              <Text size="sm" fw={600}>
                Estimated total: {estimate.total.toLocaleString()} {estimate.currency}
                {estimate.estimatedKm != null
                  ? ` · ${estimate.estimatedKm} km (straight-line estimate)`
                  : ""}
              </Text>
            </Stack>
          )}
          <NumberInput
            label="Advance amount"
            placeholder="0.00"
            required
            min={0.01}
            value={advanceAmount}
            onChange={setAdvanceAmount}
          />
          <Group justify="flex-end">
            <Button
              variant="default"
              onClick={() => {
                setApproveTarget(null);
                setAdvanceAmount("");
              }}
            >
              Cancel
            </Button>
            <Button
              disabled={!(Number(advanceAmount) > 0)}
              loading={approve.isPending}
              onClick={() => approve.mutate()}
            >
              Confirm
            </Button>
          </Group>
        </Stack>
      </Modal>

      <Modal
        opened={Boolean(rejectTarget)}
        onClose={() => setRejectTarget(null)}
        title={<Text fw={700}>Reject request{rejectTarget?.booking?.reference ? ` · ${rejectTarget.booking.reference}` : ""}</Text>}
        centered
      >
        <Stack gap="md">
          <Textarea
            label="Reason"
            placeholder="Why is this request being rejected?"
            required
            minRows={3}
            value={rejectReason}
            onChange={(e) => setRejectReason(e.currentTarget.value)}
          />
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setRejectTarget(null)}>
              Cancel
            </Button>
            <Button
              color="red"
              disabled={!rejectReason.trim()}
              loading={reject.isPending}
              onClick={() => reject.mutate()}
            >
              Confirm
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Card>
  );
}
