import {
  Alert,
  Badge,
  Box,
  Button,
  Center,
  Group,
  Loader,
  Paper,
  SimpleGrid,
  Stack,
  Stepper,
  Text,
  ThemeIcon,
  Title,
} from "@mantine/core";
import {
  IconBook2,
  IconCircleCheck,
  IconClock,
  IconDownload,
  IconFileDescription,
  IconInfoCircle,
  IconPrinter,
  IconRefresh,
  IconReplace,
  IconShield,
} from "@tabler/icons-react";
import { notifications } from "@mantine/notifications";
import {
  SEAFARER_DOCUMENT_KIND_LABELS,
  SEAFARER_DOCUMENT_REQUEST_KIND_COLORS,
  SEAFARER_DOCUMENT_REQUEST_KIND_LABELS,
  SEAFARER_DOCUMENT_STATUS_COLORS,
  SEAFARER_DOCUMENT_STATUS_LABELS,
  extractErrorMessage,
  useBypassDocumentPaymentMutation,
  useGetMySeafarerDocumentsQuery,
  useGetPaymentCapabilitiesQuery,
  useLazyGetMySeafarerDocumentDownloadQuery,
  useRenewSeafarerDocumentMutation,
  useReplaceSeafarerDocumentMutation,
  type SeafarerDocument,
  type SeafarerDocumentStatus,
} from "@ema-platform/api";
import { useApplicationPayment } from "../../payments/hooks/useApplicationPayment";

/**
 * The stages a document passes through, for the progress stepper. Derived
 * from the status the API moves, never stored separately.
 */
const STAGES: { label: string; statuses: SeafarerDocumentStatus[] }[] = [
  { label: "Requested", statuses: ["AWAITING_REGISTRATION"] },
  { label: "Payment", statuses: ["PAYMENT_PENDING"] },
  { label: "Paid", statuses: ["PAID", "PAYMENT_CONFIRMED"] },
  { label: "Pickup Scheduled", statuses: ["SCHEDULED"] },
  { label: "Issued", statuses: ["ISSUED"] },
];

function stageIndexFor(status: SeafarerDocumentStatus): number {
  let reached = -1;
  STAGES.forEach((stage, i) => {
    if (stage.statuses.includes(status)) reached = i;
  });
  return reached;
}

function formatDate(value: string): string {
  return new Date(value).toLocaleDateString("en-GB", {
    day: "2-digit",
    month: "short",
    year: "numeric",
  });
}

/** One document: where it stands, what the applicant can do about it now. */
function DocumentCard({ document, onChanged }: { document: SeafarerDocument; onChanged: () => void }) {
  const { payDocument, isPaying } = useApplicationPayment();
  const { data: capabilities } = useGetPaymentCapabilitiesQuery();
  const [bypass, { isLoading: bypassing }] = useBypassDocumentPaymentMutation();
  const [getDownload, { isFetching: downloading }] = useLazyGetMySeafarerDocumentDownloadQuery();
  const [renew, { isLoading: renewing }] = useRenewSeafarerDocumentMutation();
  const [replaceDoc, { isLoading: replacing }] = useReplaceSeafarerDocumentMutation();
  const title = SEAFARER_DOCUMENT_KIND_LABELS[document.kind];
  const activeStep = stageIndexFor(document.status);

  async function renewOrReplace(action: () => ReturnType<typeof renew>) {
    try {
      await action().unwrap();
      onChanged();
    } catch (err) {
      notifications.show({ color: "red", title: "Request failed", message: extractErrorMessage(err) });
    }
  }

  async function download() {
    try {
      const { url } = await getDownload(document.id).unwrap();
      window.open(url, "_blank", "noopener");
    } catch (err) {
      notifications.show({ color: "red", title: "Download failed", message: extractErrorMessage(err) });
    }
  }

  return (
    <Paper withBorder radius="lg" p="lg">
      <Group justify="space-between" mb="md" wrap="wrap" gap="sm">
        <Group gap="xs">
          <ThemeIcon variant="light" color="blue" size={36} radius="md">
            <IconBook2 size={18} />
          </ThemeIcon>
          <div>
            <Text fw={700}>
              {title} — {document.documentNumber ?? document.requestNumber}
            </Text>
            <Text fz="xs" c="dimmed">
              Requested {formatDate(document.createdAt)}
              {document.feeAmount !== null && ` · Fee ${document.feeAmount} ${document.feeCurrency}`}
            </Text>
          </div>
        </Group>
        <Group gap="xs">
          {document.requestKind !== "NEW" && (
            <Badge color={SEAFARER_DOCUMENT_REQUEST_KIND_COLORS[document.requestKind]} variant="outline" size="lg">
              {SEAFARER_DOCUMENT_REQUEST_KIND_LABELS[document.requestKind]}
            </Badge>
          )}
          <Badge color={SEAFARER_DOCUMENT_STATUS_COLORS[document.status]} variant="light" size="lg">
            {SEAFARER_DOCUMENT_STATUS_LABELS[document.status]}
          </Badge>
        </Group>
      </Group>

      {document.status !== "REJECTED" && document.status !== "CANCELLED" && (
        <Stepper active={activeStep} size="sm" color="teal">
          {STAGES.map((stage, i) => (
            <Stepper.Step
              key={stage.label}
              label={stage.label}
              description={i <= activeStep ? "Done" : "Pending"}
              icon={i <= activeStep ? <IconCircleCheck size={16} /> : <IconClock size={16} />}
            />
          ))}
        </Stepper>
      )}

      {document.status === "AWAITING_REGISTRATION" && (
        <Alert variant="light" color="gray" icon={<IconInfoCircle size={17} />} mt="md">
          Requested with your seafarer registration. It moves to payment as soon as the
          registration is approved.
        </Alert>
      )}
      {document.status === "PAYMENT_PENDING" && (
        <Group mt="md">
          <Button loading={isPaying} onClick={() => payDocument(document.id)}>
            Pay now
          </Button>
          {capabilities?.bypassEnabled && (
            <Button
              variant="default"
              loading={bypassing}
              onClick={async () => {
                await bypass(document.id).unwrap();
                onChanged();
              }}
            >
              Complete test payment
            </Button>
          )}
        </Group>
      )}
      {(document.status === "PAID" || document.status === "PAYMENT_CONFIRMED") && (
        <Alert variant="light" color="blue" icon={<IconInfoCircle size={17} />} mt="md">
          Payment received. The Authority will schedule a date for you to collect your {title}.
        </Alert>
      )}
      {document.status === "SCHEDULED" && document.scheduledIssuanceDate && (
        <Alert variant="light" color="grape" icon={<IconPrinter size={17} />} mt="md">
          Your {title} is ready for collection on{" "}
          <strong>{formatDate(document.scheduledIssuanceDate)}</strong>. Please visit the EMA
          office on that date, bringing your National ID.
        </Alert>
      )}
      {document.status === "ISSUED" && (
        <Alert variant="light" color="teal" icon={<IconPrinter size={17} />} mt="md">
          <Group justify="space-between" wrap="wrap">
            <span>
              Your {title} <strong>{document.documentNumber}</strong> was issued
              {document.issueDate && ` on ${formatDate(document.issueDate)}`}
              {document.expiryDate && `, valid until ${formatDate(document.expiryDate)}`}.
            </span>
            <Group gap="xs">
              <Button size="xs" variant="light" leftSection={<IconDownload size={14} />} loading={downloading} onClick={download}>
                Download PDF
              </Button>
              <Button
                size="xs"
                variant="default"
                leftSection={<IconRefresh size={14} />}
                loading={renewing}
                onClick={() => renewOrReplace(() => renew(document.id))}
              >
                Renew
              </Button>
              <Button
                size="xs"
                variant="default"
                leftSection={<IconReplace size={14} />}
                loading={replacing}
                onClick={() => renewOrReplace(() => replaceDoc(document.id))}
              >
                Report Lost/Damaged
              </Button>
            </Group>
          </Group>
        </Alert>
      )}
      {document.status === "REJECTED" && (
        <Alert variant="light" color="red" icon={<IconInfoCircle size={17} />} mt="md">
          {document.rejectionReason ?? "This request was rejected."}
        </Alert>
      )}
    </Paper>
  );
}

/**
 * The Seaman Book and Basic Training Certificate — requested automatically
 * with the seafarer registration, tracked here through payment, collection
 * and issue.
 */
export function SeamanBookPage({ service = "COMBINED" }: { service?: "COMBINED" | "SEAMAN_BOOK" | "BTC" }) {
  // Polled: payment confirmation, scheduling and issue happen in other sessions.
  const { data, isLoading, refetch } = useGetMySeafarerDocumentsQuery(undefined, {
    pollingInterval: 15_000,
  });
  const isBtc = service === "BTC";
  const isCombined = service === "COMBINED";
  const shown = [
    ...(isCombined || !isBtc ? [data?.seamanBook] : []),
    ...(isCombined || isBtc ? [data?.btc] : []),
  ].filter((d): d is SeafarerDocument => Boolean(d));

  return (
    <Stack gap="md">
      <div>
        <Title order={3}>
          {isCombined
            ? "Seaman Book & Basic Training Certificate"
            : isBtc
              ? "Basic Training Certificate"
              : "Seaman Book"}
        </Title>
        <Text fz="sm" c="dimmed">
          Both are requested for you when you register as a seafarer and released to payment once
          the registration is approved. Each is paid for separately.
        </Text>
      </div>

      {isLoading ? (
        <Center h={160}>
          <Loader />
        </Center>
      ) : shown.length === 0 ? (
        <Alert variant="light" color="blue" icon={<IconInfoCircle size={17} />}>
          Nothing requested yet. Complete and submit your seafarer registration — a Seaman Book and a
          Basic Training Certificate are applied for with it.
        </Alert>
      ) : (
        shown.map((document) => <DocumentCard key={document.id} document={document} onChanged={refetch} />)
      )}

      <Paper withBorder radius="lg" p="lg" bg="var(--mantine-color-blue-light)">
        <Group gap="xs" mb="sm">
          <IconInfoCircle size={18} color="var(--mantine-color-blue-6)" />
          <Text fw={700} fz="sm">
            About the {isCombined ? "Seaman Book & Basic Training Certificate" : isBtc ? "Basic Training Certificate" : "Seaman Book"}
          </Text>
        </Group>
        <SimpleGrid cols={{ base: 1, sm: 3 }} spacing="md">
          {(isBtc
            ? [
                { icon: IconShield, title: "STCW Training", desc: "Confirms completion of the required basic maritime safety training." },
                { icon: IconFileDescription, title: "Certificate Record", desc: "Keeps your approved basic training evidence available in one place." },
                { icon: IconCircleCheck, title: "Verified", desc: "Issued after EMA verifies the applicable training requirements." },
              ]
            : [
                { icon: IconBook2, title: "Official Identity", desc: "Internationally recognized maritime identity document required before joining any vessel." },
                { icon: IconFileDescription, title: "Service Record", desc: "Records all your sea service, vessel assignments, and employment history." },
                { icon: IconShield, title: "STCW Compliance", desc: "Required under STCW for all seafarers. Must be renewed and kept valid throughout your career." },
              ]
          ).map(({ icon: Icon, title, desc }) => (
            <Box key={title}>
              <Group gap="xs" mb={4}>
                <Icon size={16} color="var(--mantine-color-blue-6)" />
                <Text fz="sm" fw={600}>
                  {title}
                </Text>
              </Group>
              <Text fz="xs" c="dimmed" lh={1.5}>
                {desc}
              </Text>
            </Box>
          ))}
        </SimpleGrid>
      </Paper>
    </Stack>
  );
}
