import {
  Alert,
  Badge,
  Button,
  Divider,
  Group,
  Loader,
  Modal,
  Paper,
  Stack,
  Table,
  Text,
} from '@mantine/core';
import { DateTimePicker } from '@mantine/dates';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Receipt } from 'lucide-react';
import { useEffect, useState } from 'react';

import { QUERY_KEYS } from '@/constants/QUERY_KEYS';
import { useToast } from '@/hooks/use-toast';
import { isBackdated } from '@/lib/no-backdate';
import { lastMileService, type LastMileRecord } from '@/services/last-mile.service';

interface TruckDetentionModalProps {
  opened: boolean;
  onClose: () => void;
  record: LastMileRecord | null;
}

const money = (amount: number, currency: string) =>
  `${Number(amount).toLocaleString()} ${currency === 'ETB' ? 'Birr (ETB)' : currency}`;

function Stat({ label, value, strong }: { label: string; value: React.ReactNode; strong?: boolean }) {
  return (
    <Paper withBorder p="sm" radius="md" style={{ flex: 1, minWidth: 120 }}>
      <Text size="xs" c="dimmed" tt="uppercase" fw={600}>
        {label}
      </Text>
      <Text size={strong ? 'lg' : 'md'} fw={strong ? 800 : 600}>
        {value}
      </Text>
    </Paper>
  );
}

/**
 * View/override the detention clock (arrival + delivery/return) for a last-mile
 * leg, preview the per-truck-per-day charge, and generate the detention invoice.
 */
export function TruckDetentionModal({ opened, onClose, record }: TruckDetentionModalProps) {
  const { toast } = useToast();
  const qc = useQueryClient();
  const id = record?.id ?? null;
  const [arrived, setArrived] = useState<Date | null>(null);
  const [delivered, setDelivered] = useState<Date | null>(null);

  useEffect(() => {
    setArrived(record?.arrivedAt ? new Date(record.arrivedAt) : null);
    setDelivered(record?.deliveredAt ? new Date(record.deliveredAt) : null);
  }, [record?.id, record?.arrivedAt, record?.deliveredAt, opened]);

  const previewQuery = useQuery({
    queryKey: ['truck-detention-preview', id],
    queryFn: async () => (await lastMileService.truckDetentionPreview(id as string)).data,
    enabled: opened && Boolean(id),
  });
  const preview = previewQuery.data;

  const saveTimes = useMutation({
    mutationFn: () =>
      lastMileService.update(id as string, {
        arrivedAt: arrived ? arrived.toISOString() : null,
        deliveredAt: delivered ? delivered.toISOString() : null,
      }),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE.ROOT });
      void previewQuery.refetch();
      toast({ title: 'Detention times saved' });
    },
    onError: () => toast({ title: 'Save failed', variant: 'destructive' }),
  });

  const generate = useMutation({
    mutationFn: () => lastMileService.generateTruckDetentionInvoice(id as string),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: QUERY_KEYS.LAST_MILE.ROOT });
      toast({ title: 'Truck detention invoice generated' });
      onClose();
    },
    onError: (e: unknown) => {
      const description = (e as { response?: { data?: { message?: string } } })?.response?.data?.message;
      toast({ title: 'Detention invoice failed', description, variant: 'destructive' });
    },
  });

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      centered
      size="lg"
      title={
        <Text fw={700}>
          Truck detention{record?.booking?.reference ? ` · ${record.booking.reference}` : ''}
        </Text>
      }
    >
      <Stack gap="md">
        <Group grow align="flex-start">
          <DateTimePicker
            label="Arrived at"
            description="Detention clock start"
            value={arrived}
            onChange={(v) => setArrived(v ? new Date(v) : null)}
            minDate={new Date()}
            clearable
          />
          <DateTimePicker
            label="Delivered / returned at"
            description="Clock end (blank = still out)"
            value={delivered}
            onChange={(v) => setDelivered(v ? new Date(v) : null)}
            minDate={new Date()}
            clearable
          />
        </Group>
        <Group justify="flex-end">
          <Button
            variant="light"
            loading={saveTimes.isPending}
            onClick={() => {
              // No backdating: detention times are recorded as they happen.
              if (isBackdated(arrived) || isBackdated(delivered)) {
                toast({
                  variant: 'destructive',
                  title: 'Detention times cannot be in the past',
                });
                return;
              }
              saveTimes.mutate();
            }}
          >
            Save times
          </Button>
        </Group>

        <Divider label="Detention preview" labelPosition="left" />

        {previewQuery.isLoading ? (
          <Group justify="center" py="md">
            <Loader />
          </Group>
        ) : !preview ? (
          <Alert color="gray" variant="light">
            No preview available.
          </Alert>
        ) : !preview.ruleId ? (
          <Alert color="orange" variant="light">
            No active Truck Detention rule matches this booking. Create one under Warehouse → Fee rules
            (rule type "Truck Detention Cost").
          </Alert>
        ) : (
          <Stack gap="sm">
            <Group grow>
              <Stat label="Chargeable days" value={preview.chargeableDays} />
              <Stat label="Trucks" value={preview.containerCount} />
              <Stat label="Amount" value={money(preview.amount, preview.currency)} strong />
            </Group>
            {preview.endIsOpen && (
              <Text size="xs" c="orange">
                Still accruing — no delivery/return time yet. The amount grows until the vehicle is returned.
              </Text>
            )}
            {preview.groups && preview.groups.length > 1 ? (
              <Table withTableBorder withColumnBorders verticalSpacing="xs" fz="xs">
                <Table.Thead>
                  <Table.Tr>
                    <Table.Th>Truck type</Table.Th>
                    <Table.Th>Trucks</Table.Th>
                    <Table.Th>Days</Table.Th>
                    <Table.Th ta="right">Rate / truck / day</Table.Th>
                    <Table.Th ta="right">Amount</Table.Th>
                  </Table.Tr>
                </Table.Thead>
                <Table.Tbody>
                  {preview.groups.map((g, i) => (
                    <Table.Tr key={i}>
                      <Table.Td>
                        {g.vehicleType ?? 'Unknown'}
                        {!g.ruleId && (
                          <Text span size="xs" c="red">
                            {' '}· no rule
                          </Text>
                        )}
                      </Table.Td>
                      <Table.Td>{g.truckCount}</Table.Td>
                      <Table.Td>{g.chargeableDays}</Table.Td>
                      <Table.Td ta="right">{money(g.ratePerDay, preview.currency)}</Table.Td>
                      <Table.Td ta="right">{money(g.amount, preview.currency)}</Table.Td>
                    </Table.Tr>
                  ))}
                </Table.Tbody>
              </Table>
            ) : preview.tiers && preview.tiers.length > 0 ? (
              <Table withTableBorder withColumnBorders verticalSpacing="xs" fz="xs">
                <Table.Thead>
                  <Table.Tr>
                    <Table.Th>From day</Table.Th>
                    <Table.Th>To day</Table.Th>
                    <Table.Th>Days</Table.Th>
                    <Table.Th ta="right">Rate / truck / day</Table.Th>
                    <Table.Th ta="right">Amount</Table.Th>
                  </Table.Tr>
                </Table.Thead>
                <Table.Tbody>
                  {preview.tiers.map((t, i) => (
                    <Table.Tr key={i}>
                      <Table.Td>{t.appliedFromDay}</Table.Td>
                      <Table.Td>{t.appliedToDay}</Table.Td>
                      <Table.Td>{t.days}</Table.Td>
                      <Table.Td ta="right">{money(t.ratePerDay, preview.currency)}</Table.Td>
                      <Table.Td ta="right">{money(t.amount, preview.currency)}</Table.Td>
                    </Table.Tr>
                  ))}
                </Table.Tbody>
              </Table>
            ) : (
              <Text size="sm" c="dimmed">
                Flat {money(preview.ratePerDay, preview.currency)} per truck per day after the grace window.
              </Text>
            )}
            <Group gap="xs">
              <Badge variant="light" color="gray">
                {preview.ruleName ?? 'Detention rule'}
              </Badge>
              {preview.billableUnits > 0 && (
                <Text size="xs" c="dimmed">
                  {preview.billableUnits} billable truck-day(s)
                </Text>
              )}
            </Group>
          </Stack>
        )}

        <Group justify="flex-end" mt="sm">
          <Button variant="default" onClick={onClose}>
            Close
          </Button>
          <Button
            color="edr-green"
            leftSection={<Receipt size={16} />}
            disabled={!preview || preview.amount <= 0}
            loading={generate.isPending}
            onClick={() => generate.mutate()}
          >
            Generate invoice
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}
