import { Box, Group, Text } from "@mantine/core";
import { useMutation } from "@tanstack/react-query";
import { CreditCard, Download } from "lucide-react";
import { useState } from "react";
import { useNavigate } from "react-router-dom";

import { api } from "@/services/api";
import { paymentsService, type PaymentMethod } from "@/services/payments.service";
import type { Freight } from "@edr/types";

import { ActivityCard } from "./components/ActivityCard";
import { ClearanceCard } from "./components/ClearanceCard";
import { ContainersCard } from "./components/ContainersCard";
import { ContractCard } from "./components/ContractCard";
import { DocRow, IconSquare } from "./components/Documents";
import { KeyFactsStrip } from "./components/KeyFactsStrip";
import { BodyGrid, CardTitle, PageShell, SectionCard } from "./components/layout";
import {
  CancelledBanner,
  ConsolidationPairedNotice,
  ConsolidationWaitingBanner,
} from "./components/Notices";
import { HeaderButton, PageHeader } from "./components/PageHeader";
import { PaymentDeadlineCard } from "./components/PaymentDeadlineCard";
import { PaymentMethodModal } from "./components/PaymentMethodModal";
import { PaymentCard } from "./components/pricing";
import { ScheduleCard } from "./components/ScheduleCard";
import { ShipmentDetailsCard } from "./components/ShipmentDetailsCard";
import { StatusHero } from "./components/StatusHero";
import { SupportCard } from "./components/SupportCard";
import { fmtDate, isNegative, priceTotal } from "./utils";

export function ReadonlyBookingView({ booking }: { booking: Freight.IBooking }) {
  const navigate = useNavigate();
  const status = booking.status as string;
  const [payModalOpen, setPayModalOpen] = useState(false);

  // POST /payments/initiate creates the intent and returns the provider's
  // redirect URL (clientAction.url). Send the browser straight there; fall back
  // to the public /payments/checkout page if no redirect URL came back.
  const payMutation = useMutation({
    mutationFn: (method: PaymentMethod) =>
      api.payments.initiate.call({ bookingId: booking.id, method }),
    onSuccess: (data, method) => {
      const redirectUrl =
        data?.clientAction?.type === "REDIRECT" && data.clientAction.url
          ? data.clientAction.url
          : paymentsService.checkoutUrl({ bookingId: booking.id, method });
      window.location.href = redirectUrl;
    },
  });

  const pricing = booking.pricingBreakdown;
  // A general contract is paid once it's FULLY_EXECUTED (signed) — it never
  // enters batch selection. A one-time booking can only pay once it's been
  // SELECTED_FOR_BATCH (assigned a slot with a pay window).
  const isGeneralContract = booking.bookingType === "GENERAL_CONTRACT";
  const canPay =
    booking.paymentStatus !== "PAID" &&
    (isGeneralContract
      ? status === "FULLY_EXECUTED"
      : status === "SELECTED_FOR_BATCH");
  const showCountdown = canPay && !!booking.paymentDeadline;
  const isExpired = status === "EXPIRED";
  const isPendingConsolidation = status === "PENDING_CONSOLIDATION";
  const isClearance = [
    "AWAITING_DOCUMENTS",
    "DOCUMENTS_UNDER_REVIEW",
    "CLEARANCE_READY",
    "OPERATION_REQUESTED",
  ].includes(status);
  // Paired: a consolidation partner was found and the booking resumed the normal
  // flow. Surface the "partner found" reassurance only in the early stages,
  // before approval, so it doesn't linger for the rest of the booking's life.
  const showPairedNotice =
    !!booking.consolidationPartnerId &&
    ["SUBMITTED", "PENDING_APPROVAL", "CHANGES_REQUESTED"].includes(status);

  return (
    <PageShell>
      <PageHeader
        booking={booking}
        actions={
          canPay &&
          !showCountdown && (
            <HeaderButton
              green
              icon={<CreditCard size={16} />}
              label="Pay now"
              onClick={() => setPayModalOpen(true)}
            />
          )
        }
        menuActions={{
          onViewContract: booking.signedByCeoAt ? () => {} : undefined,
          onRebook: () => navigate("/bookings/new"),
          onSupport: () => navigate("/support"),
        }}
      />

      {isNegative(status) ? (
        <CancelledBanner
          pillLabel={status === "REJECTED" ? "Rejected" : "Cancelled"}
          title={`This booking was ${
            status === "REJECTED" ? "rejected" : "cancelled"
          } on ${fmtDate(booking.updatedAt)}.`}
          subtitle={
            status === "REJECTED"
              ? "This booking request has been rejected."
              : "This booking process has been terminated."
          }
          reason={booking.latestChangeRequestNote}
          onRebook={() => navigate("/bookings/new")}
        />
      ) : isExpired ? (
        <CancelledBanner
          pillLabel="Expired"
          title={`The payment window expired on ${fmtDate(booking.updatedAt)}.`}
          subtitle="Payment wasn't completed in time, so this booking lost its slot. Rebook to try another schedule."
          onRebook={() => navigate("/bookings/new")}
        />
      ) : isPendingConsolidation ? (
        <ConsolidationWaitingBanner
          priceLabel={pricing ? priceTotal(pricing) : undefined}
        />
      ) : (
        <StatusHero booking={booking} />
      )}

      {showPairedNotice && <ConsolidationPairedNotice />}

      <KeyFactsStrip booking={booking} />

      <ContractCard booking={booking} navigate={navigate} />

      {isClearance && <ClearanceCard booking={booking} />}

      <BodyGrid
        left={
          <>
            <ShipmentDetailsCard booking={booking} />

            <ContainersCard booking={booking} />

            {booking.files && booking.files.length > 0 && (
              <SectionCard>
                <Group justify="space-between" align="center" mb="md">
                  <CardTitle>Documents</CardTitle>
                  <Text fz="12.5px" fw={600} c="#9AA8B5">
                    {booking.files.length} files
                  </Text>
                </Group>
                <Box>
                  {booking.files.map((file, i) => (
                    <DocRow
                      key={file.id}
                      last={i === booking.files!.length - 1}
                      title={file.name}
                      meta={file.code.replace(/_/g, " ")}
                      status="verified"
                      action={
                        <IconSquare
                          href={file.signedUrl ?? file.url}
                          icon={<Download size={16} />}
                        />
                      }
                    />
                  ))}
                </Box>
              </SectionCard>
            )}

            <ActivityCard booking={booking} />
          </>
        }
        right={
          <>
            {showCountdown && (
              <PaymentDeadlineCard
                paymentDeadline={booking.paymentDeadline!}
                onPay={() => setPayModalOpen(true)}
                paying={payMutation.isPending}
              />
            )}
            <PaymentCard booking={booking} pricing={pricing} />
            <ScheduleCard
              booking={booking}
              title="Consignment & Schedule"
              consignment
            />
            <SupportCard />
          </>
        }
      />

      <PaymentMethodModal
        opened={payModalOpen}
        onClose={() => {
          if (!payMutation.isPending) {
            setPayModalOpen(false);
            payMutation.reset();
          }
        }}
        amountLabel={pricing ? priceTotal(pricing) : undefined}
        currency={pricing?.currency ?? booking.paymentCurrency}
        processing={payMutation.isPending}
        error={
          payMutation.isError
            ? payMutation.error instanceof Error
              ? payMutation.error.message
              : "Could not start payment. Please try again."
            : null
        }
        onConfirm={(method) => payMutation.mutate(method)}
      />
    </PageShell>
  );
}
