import type { ReactNode } from "react";
import {
  Modal,
  Group,
  Stack,
  Text,
  Box,
  Button,
  Textarea,
  FileInput,
  NumberInput,
} from "@mantine/core";

import type { BookingActionDef } from "@/features/bookings/booking-actions.config";

/** Today + `days`, formatted as a readable date for the validity preview. */
function validUntilLabel(days: number): string {
  const until = new Date();
  until.setDate(until.getDate() + days);
  return until.toLocaleDateString(undefined, {
    year: "numeric",
    month: "short",
    day: "numeric",
  });
}

interface BookingConfirmDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  action: BookingActionDef | null;
  reference?: string;
  inputValue: string;
  onInputChange: (value: string) => void;
  selectedFile?: File | null;
  onFileChange?: (file: File | null) => void;
  onConfirm: () => void;
  isPending: boolean;
  confirmDisabled?: boolean;
  extra?: ReactNode;
}

export function BookingConfirmDialog({
  open,
  onOpenChange,
  action,
  reference,
  inputValue,
  onInputChange,
  selectedFile = null,
  onFileChange,
  onConfirm,
  isPending,
  confirmDisabled = false,
  extra,
}: BookingConfirmDialogProps) {
  if (!action || !action.confirmTitle) return null;

  const Icon = action.icon;
  const needsTextInput = action.input === "note" || action.input === "reason";
  const needsFileInput = action.input === "file";
  const needsDaysInput = action.input === "days";
  const needsAmountInput = action.input === "amount";
  const daysValue = Number(inputValue.trim());
  const daysValid =
    Number.isInteger(daysValue) && daysValue >= 1 && daysValue <= 365;
  const amountValue = Number(inputValue.trim());
  const amountValid = !!inputValue.trim() && Number.isFinite(amountValue) && amountValue >= 0;
  const inputMissing =
    (needsTextInput && !inputValue.trim()) ||
    (needsFileInput && !selectedFile) ||
    (needsDaysInput && !daysValid) ||
    (needsAmountInput && !amountValid);
  const isDestructive = action.variant === "destructive";
  const accent = isDestructive ? "red" : "edr-green";

  return (
    <Modal
      opened={open}
      onClose={() => onOpenChange(false)}
      withCloseButton={false}
      centered
      radius="md"
      size="md"
      padding={0}
      title={null}
    >
      {/* Header */}
      <Box
        px="lg"
        py="md"
        style={{
          background: `var(--mantine-color-${accent}-0)`,
          borderBottom: `1px solid var(--mantine-color-${accent}-1)`,
        }}
      >
        <Group align="flex-start" gap="sm" wrap="nowrap">
          <Box
            style={{
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              width: 44,
              height: 44,
              borderRadius: 12,
              flexShrink: 0,
              background: `var(--mantine-color-${accent}-1)`,
              color: `var(--mantine-color-${accent}-7)`,
            }}
          >
            <Icon size={20} />
          </Box>
          <Stack gap={2} style={{ minWidth: 0 }}>
            <Text fw={700} size="md" style={{ lineHeight: 1.3 }}>
              {action.confirmTitle}
            </Text>
            {reference && (
              <Text size="xs" c="dimmed" ff="monospace" fw={600}>
                {reference}
              </Text>
            )}
          </Stack>
        </Group>
        {action.confirmDescription && (
          <Text size="sm" c="dimmed" mt="sm" style={{ lineHeight: 1.5 }}>
            {action.confirmDescription}
          </Text>
        )}
      </Box>

      {/* Body */}
      <Stack gap="md" px="lg" py="lg">
        {needsTextInput && (
          <Textarea
            label={action.inputLabel}
            withAsterisk
            value={inputValue}
            onChange={(e) => onInputChange(e.currentTarget.value)}
            placeholder={action.inputPlaceholder}
            minRows={4}
            autosize
          />
        )}
        {needsFileInput && (
          <FileInput
            label={action.inputLabel ?? "Bank slip file"}
            withAsterisk
            placeholder="Select a file"
            accept=".pdf,.png,.jpg,.jpeg"
            value={selectedFile}
            onChange={(file) => onFileChange?.(file)}
            clearable
          />
        )}
        {needsDaysInput && (
          <Stack gap={4}>
            <NumberInput
              label={action.inputLabel ?? "Contract validity (days)"}
              withAsterisk
              min={1}
              max={365}
              clampBehavior="strict"
              allowDecimal={false}
              allowNegative={false}
              placeholder={action.inputPlaceholder ?? "e.g. 30"}
              value={inputValue === "" ? "" : Number(inputValue)}
              onChange={(value) => onInputChange(value === "" ? "" : String(value))}
            />
            <Text size="xs" c="dimmed">
              {daysValid
                ? `Contract valid from today until ${validUntilLabel(daysValue)} (${daysValue} day${daysValue === 1 ? "" : "s"}).`
                : "Enter a whole number of days between 1 and 365."}
            </Text>
          </Stack>
        )}
        {needsAmountInput && (
          <NumberInput
            label={action.inputLabel ?? "Adjusted total"}
            withAsterisk
            min={0}
            allowNegative={false}
            decimalScale={2}
            thousandSeparator=","
            placeholder={action.inputPlaceholder ?? "0.00"}
            value={inputValue === "" ? "" : Number(inputValue)}
            onChange={(value) => onInputChange(value === "" ? "" : String(value))}
          />
        )}
        {extra}
      </Stack>

      {/* Footer */}
      <Group
        justify="flex-end"
        gap="sm"
        px="lg"
        py="md"
        style={{
          borderTop: "1px solid var(--mantine-color-gray-2)",
          background: "var(--mantine-color-gray-0)",
        }}
      >
        <Button variant="default" disabled={isPending} onClick={() => onOpenChange(false)}>
          Cancel
        </Button>
        <Button
          color={accent}
          loading={isPending}
          disabled={inputMissing || confirmDisabled}
          leftSection={<Icon size={16} />}
          onClick={onConfirm}
          miw={112}
        >
          {action.shortLabel}
        </Button>
      </Group>
    </Modal>
  );
}
