import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import toast from "react-hot-toast";
import {
  ArrowLeft,
  Container as ContainerIcon,
  FileSignature,
  FileText,
  Flame,
  FolderOpen,
  Layers,
  LayoutGrid,
  Link2,
  Milestone,
  MoreHorizontal,
  Package,
  Receipt,
  RefreshCw,
  Ship,
  Train,
  Truck,
  Wallet,
  Weight,
} from "lucide-react";
import {
  ActionIcon,
  Alert,
  Badge,
  Box,
  Button,
  Center,
  Container,
  Grid,
  Group,
  Loader,
  Menu,
  Paper,
  SegmentedControl,
  Stack,
  Tabs,
  Text,
} from "@mantine/core";

import { PageContainer, PageHeader, KpiStrip } from "@/components/page";
import { extractDownloadErrorMessage } from "@/components/warehouses/options";
import type { KpiItem } from "@/components/page";
import { EntityLink } from "@/components/detail";
import { BookingActionsToolbar } from "@/components/bookings/BookingActionsToolbar";
import { BookingPricingSummary } from "@/components/bookings/BookingPricingSummary";
import { BookingWorkflowStepper } from "@/components/bookings/BookingWorkflowStepper";
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
import { NextStepBanner } from "@/components/bookings/NextStepBanner";
import { SchedulingStatusBadge } from "@/components/trainScheduling/ScheduleStatusBadge";
import { ConsolidationWaitingBanner } from "@/components/bookings/detail/ConsolidationWaitingBanner";
import { ConsolidationApprovalCard } from "@/components/bookings/detail/ConsolidationApprovalCard";
import {
  detailStyles,
  BookingRouteServiceCard,
  BookingMileServicesCard,
  BookingCargoCard,
  BookingCompanyCard,
  BookingContractCard,
  BookingContainerUnitsCard,
  BookingSchedulingWindowCard,
  BookingDocumentsPanel,
  BookingTrucksPanel,
  BookingWagonsPanel,
  ContractOrdersPanel,
} from "@/components/bookings/detail";
import { WarehouseInfoCard } from "@/components/warehouses";
import { AdditionalPaymentsTab } from "@/components/bookings/AdditionalPaymentsTab";
import { getStatusMeta } from "@/features/bookings/booking-status.config";
import { toBookingListRow } from "@/features/bookings/mapBookingListRow";
import { formatDateTime, formatMoney } from "@/lib/format";
import { currencyDecimals } from "@edr/ui-common";
import { cargoTonsAndItems } from "@/utils/cargoWeight";
import type { BookingDetail } from "@/types/booking";
import {
  useBookingDetail,
  useBookingMutations,
} from "@/hooks/bookings/useBookings";
import { useScrollToHash } from "@/hooks/useScrollToHash";
import { useFileViewer } from "@/hooks/useFileViewer";
import { bookingsService } from "@/services/bookings.service";
import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission as hasFreightPermission } from "@/lib/permissions";
import { WagonCancellationCreditCard } from "@/components/bookings/wagon-cancellation";

export default function BookingRequestDetailPage() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  // Deep-link from a warehouse fee invoice → this booking's warehouse section.
  useScrollToHash();
  const { view, viewer } = useFileViewer();
  const { user } = useAuth();
  const canSeeAdditionalCharges = hasFreightPermission(
    user,
    FREIGHT_PERMS.additionalCharges.view,
  );

  // Consolidated pair: `?booking=<partnerId>` swaps the WHOLE page over to the
  // other half of the shared wagon. Everything below — KPIs, stepper, the
  // overview/orders/documents/trucks sub-tabs, the action toolbar — then reads
  // from the selected booking, so each half gets its own complete detail page
  // under a top-level tab. The URL id stays put so Back still works.
  const selectedId = searchParams.get("booking") || id;
  const {
    data: booking,
    isLoading,
    isError,
    refetch,
    isFetching,
  } = useBookingDetail(selectedId);
  const mutations = useBookingMutations(selectedId ?? "");

  // The pair is discovered from whichever half is on screen: each booking
  // carries a reference to the other.
  const routeBookingId = id ?? "";
  const partnerId = booking?.consolidationPartnerId ?? null;
  const isPaired = Boolean(partnerId);
  const viewingPartner = selectedId !== routeBookingId;
  // Tab identities: the booking named by the URL is always the first tab, the
  // other half the second — regardless of which one is currently displayed.
  const firstTabId = routeBookingId;
  const secondTabId = viewingPartner ? selectedId : partnerId;

  // Only for the tab label (reference + customer) — the displayed half is
  // loaded above. Skipped entirely when the booking is not part of a pair.
  const { data: otherBooking } = useBookingDetail(
    secondTabId && secondTabId !== selectedId ? secondTabId : undefined,
  );
  const firstTabBooking = viewingPartner ? otherBooking : booking;
  const secondTabBooking = viewingPartner ? booking : otherBooking;

  const selectBooking = (bookingId: string) => {
    const next = new URLSearchParams(searchParams);
    if (bookingId === routeBookingId) next.delete("booking");
    else next.set("booking", bookingId);
    // Switching booking resets the sub-tab: the other half has its own content
    // and may not even have the tab that was open (e.g. Orders).
    next.delete("tab");
    setSearchParams(next, { replace: true });
  };

  if (isLoading) {
    return (
      <PageContainer>
        <Center mih="60vh">
          <Stack align="center" gap="md">
            <Loader color="gray" />
            <Text size="sm" c="dimmed" fw={500}>
              Loading booking…
            </Text>
          </Stack>
        </Center>
      </PageContainer>
    );
  }

  if (isError || !booking) {
    return (
      <PageContainer>
        <Container size="sm" py="xl">
          <Paper
            radius="md"
            withBorder
            p="xl"
            ta="center"
            style={detailStyles.card}
          >
            <Center>
              <Box
                style={{
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  width: 64,
                  height: 64,
                  borderRadius: 16,
                  background: "var(--mantine-color-gray-1)",
                  color: "var(--mantine-color-gray-6)",
                }}
              >
                <Package size={32} />
              </Box>
            </Center>
            <Text fw={700} size="lg" mt="lg">
              Booking not found
            </Text>
            <Text size="sm" c="dimmed" mt={4}>
              This request may have been removed or the link is invalid.
            </Text>
            <Button
              variant="default"
              mt="lg"
              leftSection={<ArrowLeft size={16} />}
              onClick={() => navigate("/dashboard/booking-requests")}
            >
              Back to booking requests
            </Button>
          </Paper>
        </Container>
      </PageContainer>
    );
  }

  const statusMeta = getStatusMeta(booking.status);
  // Clearance review + finalize now lives solely on the Operations "Clearance
  // Documents" hub (/dashboard/contracts/clearance-documents → detail page), so
  // no clearance tab is embedded here anymore.
  // A general contract drives an "Orders" tab: each drawdown order spawns a
  // child booking that staff manage (clearance/approval) independently.
  const isGeneralContract = booking.bookingType === "GENERAL_CONTRACT";
  // The Documents tab is always available — every booking can accrue clearance,
  // customs-workflow, invoice or notice files — so the tab bar always renders.
  const requestedTab = searchParams.get("tab");
  const activeTab =
    requestedTab === "orders" && isGeneralContract
      ? "orders"
      : requestedTab === "documents"
        ? "documents"
        : requestedTab === "trucks"
          ? "trucks"
          : requestedTab === "wagons"
            ? "wagons"
            : requestedTab === "additional-charges"
              ? "additional-charges"
              : "overview";
  const setActiveTab = (tab: string | null) => {
    const next = new URLSearchParams(searchParams);
    if (tab && tab !== "overview") next.set("tab", tab);
    else next.delete("tab");
    setSearchParams(next, { replace: true });
  };

  const company = booking.company;
  const shippingLine = booking.shippingLineCompany ?? null;
  const customerName = toBookingListRow(booking).customerLabel;
  // What is being shipped, in words: bulk → the commodity (Wheat, Steel…);
  // containers → the shipper's own description when given.
  const cargoLabel =
    booking.freightType === "BULK"
      ? (booking.cargoType?.label ?? booking.cargoType?.name ?? null)
      : (booking.cargoFreeText?.trim() || null);

  const amount = Number(booking.totalAmount);
  const containers = booking.bookingContainers ?? [];
  const containerCount = containers.reduce(
    (sum, c) => sum + Number(c.quantity ?? 0),
    0,
  );
  const { tons: weight, items: itemCount } = cargoTonsAndItems(booking);

  const kpis: KpiItem[] = [
    {
      label: "Total value",
      value: formatMoney(amount, booking.paymentCurrency, currencyDecimals(booking.paymentCurrency)),
      hint: booking.paymentStatus,
      icon: Wallet,
      color: "edr-green",
    },
    {
      label: "Cargo weight",
      value: `${weight} T`,
      hint: itemCount != null ? `${itemCount} items` : "VGM total",
      icon: Weight,
      color: "blue",
    },
    {
      label: "Containers",
      value: containerCount || "—",
      hint: `${containers.length} line${containers.length === 1 ? "" : "s"}`,
      icon: ContainerIcon,
      color: "teal",
    },
    {
      label: "Priority score",
      value: booking.priorityScore ?? 0,
      hint: booking.tradeDirection,
      icon: Flame,
      color: "orange",
    },
  ];

  const hasSignableContract = booking.isGovernment && booking.contractSummary;

  return (
    <PageContainer>
      <PageHeader
        breadcrumbs={[
          { label: "Booking requests", href: "/dashboard/booking-requests" },
          { label: booking.reference },
        ]}
        backTo="/dashboard/booking-requests"
        title={booking.reference}
        meta={
          <Group gap={6} wrap="wrap">
            <BookingStatusBadge status={booking.status} />
            <BookingPriorityBadge score={booking.priorityScore} />
            {booking.schedulingStatus ? (
              <SchedulingStatusBadge status={booking.schedulingStatus} />
            ) : null}
          </Group>
        }
        subtitle={
          <Group gap={6} wrap="wrap">
            {shippingLine ? (
              <Group gap={6} wrap="nowrap">
                <Ship size={14} />
                <Text size="sm" fw={600}>
                  {shippingLine.name}
                </Text>
                <Badge size="xs" radius="sm" variant="light" color="teal">
                  Shipping line
                </Badge>
              </Group>
            ) : (
              <EntityLink
                to={company?.id ? `/dashboard/customers/${company.id}` : null}
                label={customerName ?? "—"}
              />
            )}
            {cargoLabel ? (
              <Text size="sm" c="dimmed">
                · {cargoLabel}
              </Text>
            ) : null}
            <Text size="sm" c="dimmed">
              · Scheduled {booking.scheduledDate}
            </Text>
          </Group>
        }
        action={
          <Group gap="sm" wrap="nowrap">
            <ActionIcon
              variant="light"
              color="edr-green"
              size="lg"
              radius="md"
              loading={isFetching}
              aria-label="Refresh"
              onClick={() => refetch()}
            >
              <RefreshCw size={16} />
            </ActionIcon>
            <Menu position="bottom-end" width={260} withinPortal>
              <Menu.Target>
                <ActionIcon
                  variant="default"
                  size="lg"
                  radius="md"
                  aria-label="More actions"
                >
                  <MoreHorizontal size={16} />
                </ActionIcon>
              </Menu.Target>
              <Menu.Dropdown>
                {hasSignableContract && (
                  <Menu.Item
                    leftSection={<FileSignature size={15} />}
                    onClick={() =>
                      navigate(`/dashboard/booking-requests/${booking.id}/contract`)
                    }
                  >
                    View / sign contract
                  </Menu.Item>
                )}
                <Menu.Item
                  leftSection={<FileText size={15} />}
                  onClick={async () => {
                    try {
                      const blob =
                        await bookingsService.downloadCarriageAcceptanceSheet(
                          booking.id,
                        );
                      const url = URL.createObjectURL(blob);
                      const a = document.createElement("a");
                      a.href = url;
                      a.download = `carriage-acceptance-${booking.reference}.pdf`;
                      a.click();
                      URL.revokeObjectURL(url);
                    } catch (error) {
                      // Blob response: the JSON reason is inside the Blob, so
                      // the sync path would show only "status code 400".
                      toast.error(await extractDownloadErrorMessage(error));
                    }
                  }}
                >
                  Carriage acceptance sheet
                </Menu.Item>
                {booking.customsClearingEnabled && (
                  <Menu.Item
                    leftSection={<Milestone size={15} />}
                    onClick={() =>
                      navigate(`/dashboard/bookings/${booking.id}/clearance`)
                    }
                  >
                    View document clearance
                  </Menu.Item>
                )}
              </Menu.Dropdown>
            </Menu>
          </Group>
        }
      />

      <Stack gap="lg">
        {/* Consolidated pair: one tab per booking, switching the ENTIRE page
            below. The overview/orders/documents/trucks tabs further down are
            sub-tabs of whichever booking is selected here. */}
        {isPaired && secondTabId ? (
          <Tabs
            value={selectedId ?? undefined}
            onChange={(value) => value && selectBooking(value)}
            variant="pills"
            radius="md"
          >
            <Tabs.List>
              <Tabs.Tab value={firstTabId} leftSection={<Link2 size={15} />}>
                <Stack gap={0} align="flex-start">
                  <Text fz={13} fw={700}>
                    {firstTabBooking?.reference ?? "Booking"}
                  </Text>
                  <Text fz={11} c="dimmed">
                    {firstTabBooking?.company?.name ?? "—"}
                  </Text>
                </Stack>
              </Tabs.Tab>
              <Tabs.Tab value={secondTabId} leftSection={<Link2 size={15} />}>
                <Stack gap={0} align="flex-start">
                  <Text fz={13} fw={700}>
                    {secondTabBooking?.reference ?? "Partner booking"}
                  </Text>
                  <Text fz={11} c="dimmed">
                    {secondTabBooking?.company?.name ?? "—"}
                  </Text>
                </Stack>
              </Tabs.Tab>
            </Tabs.List>
          </Tabs>
        ) : null}

        {isPaired ? (
          <Text size="xs" c="dimmed">
            These two bookings share one wagon. Accepting or cancelling applies
            to both; each is invoiced and paid separately.
          </Text>
        ) : null}

        <KpiStrip items={kpis} />

        {booking.holdExpiresAt && booking.schedulingStatus === "HOLDING" ? (
          <Text size="xs" c="orange.7">
            Hold expires {formatDateTime(booking.holdExpiresAt)}
          </Text>
        ) : null}

        {booking.nextStep ? (
          <Paper
            radius="lg"
            p={4}
            style={{
              background: "var(--mantine-color-gray-0)",
              border: "1px solid var(--mantine-color-gray-2)",
            }}
          >
            <NextStepBanner nextStep={booking.nextStep} />
          </Paper>
        ) : null}

        <BookingWorkflowStepper
          status={booking.status}
          title={statusMeta.title}
          description={statusMeta.description}
          titleColor={statusMeta.color}
        />

        {booking.status === "PENDING_CONSOLIDATION" && (
          <ConsolidationWaitingBanner bookingId={booking.id} />
        )}

        {booking.status === "CONSOLIDATION_APPROVAL_PENDING" && (
          <Alert
            color="yellow"
            radius="md"
            icon={<Link2 size={18} />}
            title="Waiting for shared-wagon approval"
          >
            <Text size="sm">
              This booking shares a wagon with another customer&apos;s booking.
              Both are held here until the pairing is approved — neither reaches
              Operations before then.
            </Text>
          </Alert>
        )}

        <Grid gap="lg">
          {/* LEFT — primary content, split into tabs to keep each view focused.
              The Documents tab is always present, so the tab bar always renders. */}
          <Grid.Col span={{ base: 12, lg: 8 }}>
            <Tabs
                value={activeTab}
                onChange={setActiveTab}
                variant="pills"
                color="edr-blue"
                keepMounted={false}
              >
                <Tabs.List mb="lg">
                  <Tabs.Tab
                    value="overview"
                    leftSection={<LayoutGrid size={16} />}
                  >
                    Overview
                  </Tabs.Tab>
                  {isGeneralContract && (
                    <Tabs.Tab value="orders" leftSection={<Layers size={16} />}>
                      Orders
                    </Tabs.Tab>
                  )}
                  <Tabs.Tab
                    value="documents"
                    leftSection={<FolderOpen size={16} />}
                  >
                    Documents
                  </Tabs.Tab>
                  <Tabs.Tab value="trucks" leftSection={<Truck size={16} />}>
                    Trucks
                  </Tabs.Tab>
                  <Tabs.Tab value="wagons" leftSection={<Train size={16} />}>
                    Wagons
                  </Tabs.Tab>
                  {canSeeAdditionalCharges && (
                    <Tabs.Tab
                      value="additional-charges"
                      leftSection={<Receipt size={16} />}
                    >
                      Additional payments
                    </Tabs.Tab>
                  )}
                </Tabs.List>

                <Tabs.Panel value="overview">
                  <OverviewPanel booking={booking} onRefetch={refetch} />
                </Tabs.Panel>
                {isGeneralContract && (
                  <Tabs.Panel value="orders">
                    <ContractOrdersPanel
                      contractBookingId={booking.id}
                      isContainer={booking.freightType === "CONTAINER"}
                    />
                  </Tabs.Panel>
                )}
                <Tabs.Panel value="documents">
                  <BookingDocumentsPanel bookingId={booking.id} />
                </Tabs.Panel>
                <Tabs.Panel value="trucks">
                  <BookingTrucksPanel bookingId={booking.id} />
                </Tabs.Panel>
                <Tabs.Panel value="wagons">
                  <BookingWagonsPanel
                    bookingId={booking.id}
                    bookingReference={booking.reference}
                  />
                </Tabs.Panel>
                {canSeeAdditionalCharges && (
                  <Tabs.Panel value="additional-charges">
                    <AdditionalPaymentsTab bookingId={booking.id} onViewFile={view} />
                  </Tabs.Panel>
                )}
              </Tabs>
          </Grid.Col>

          {/* RIGHT — sticky action / summary rail */}
          <Grid.Col span={{ base: 12, lg: 4 }}>
            <Box style={{ position: "sticky", top: 24 }}>
              <Stack gap="lg">
                <BookingCompanyCard booking={booking} />
                <BookingContractCard booking={booking} />
                <BookingPricingSummary booking={booking} />
                <Box id="warehouse-payments">
                  <WarehouseInfoCard
                    bookingId={booking.id}
                    bookingReference={booking.reference}
                    paymentStatus={booking.paymentStatus}
                    tradeDirection={booking.tradeDirection}
                  />
                </Box>
                {/* Sits directly above the staff actions: reviewing an operation
                    request means approving the booking onto a specific train, so
                    that train and its clock must be readable before the approve
                    button. */}
                <BookingSchedulingWindowCard booking={booking} />
                {/* Renders itself only when this booking has a shared wagon. */}
                <ConsolidationApprovalCard bookingId={booking.id} />
                <BookingActionsToolbar
                  booking={booking}
                  mutations={mutations}
                />
              </Stack>
            </Box>
          </Grid.Col>
        </Grid>
      </Stack>
      {viewer}
    </PageContainer>
  );
}

/** The booking's primary detail cards — route, services, cargo, containers. */
function OverviewPanel({
  booking,
  onRefetch,
}: {
  booking: BookingDetail;
  onRefetch: () => void;
}) {
  const row = toBookingListRow(booking);

  return (
    <Stack gap="lg">
      <BookingRouteServiceCard
        booking={booking}
        originLabel={row.originLabel}
        destinationLabel={row.destinationLabel}
      />
      <BookingMileServicesCard
        booking={booking}
        handoverSection={
          booking.tradeDirection === "EXPORT" ? (
            <Stack gap={6}>
              <Text size="sm" fw={600}>
                How the cargo reaches the train
              </Text>
              <SegmentedControl
                fullWidth
                size="xs"
                value={booking.exportHandoverMode ?? "WAREHOUSE"}
                data={[
                  { value: "WAREHOUSE", label: "Warehouse then train" },
                  { value: "DIRECT_TO_TRAIN", label: "Direct truck to train" },
                ]}
                onChange={async (value) => {
                  try {
                    await bookingsService.setExportHandoverMode(
                      booking.id,
                      value as "DIRECT_TO_TRAIN" | "WAREHOUSE",
                    );
                    onRefetch();
                  } catch (error) {
                    toast.error(
                      error instanceof Error
                        ? error.message
                        : "Could not change the handover mode",
                    );
                  }
                }}
              />
              <Text size="xs" c="dimmed">
                {booking.exportHandoverMode === "DIRECT_TO_TRAIN"
                  ? "No warehouse receipt and no GRN — the carriage acceptance sheet is the handover document."
                  : "Cargo is received at the warehouse and issued a GRN before loading."}
              </Text>
            </Stack>
          ) : null
        }
      />
      <BookingCargoCard booking={booking} />
      <BookingContainerUnitsCard booking={booking} />
      <WagonCancellationCreditCard bookingId={booking.id} onRebooked={onRefetch} />
    </Stack>
  );
}
