import type { Freight } from "@edr/types";
import {
  Alert,
  Badge,
  Button,
  Group,
  Paper,
  Stack,
  Text,
  TextInput,
  Textarea,
} from "@mantine/core";
import { useMutation } from "@tanstack/react-query";
import { CheckCircle2, Clock, Send, UserCheck } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";

import { contractsService } from "@/services/contracts.service";

export interface TransitAssigneePanelProps {
  contractId: string;
  transitAssignee: Freight.ContractClearanceView["transitAssignee"];
  /**
   * ET asks and waits; DJ answers with a name. The same state renders from both
   * desks — only the action on offer differs.
   */
  side: "ET" | "DJ";
  /** Hide the action (read-only audit view, or the user lacks the permission). */
  readOnly?: boolean;
  onChanged?: () => void;
}

const fmt = (iso?: string | null) =>
  iso
    ? new Date(iso).toLocaleString("en-GB", {
        day: "numeric",
        month: "short",
        hour: "2-digit",
        minute: "2-digit",
        hour12: false,
      })
    : "—";

/**
 * The transit-assignee handshake that gates the customs declaration.
 *
 * GL Ethiopia cannot file a declaration until Djibouti says who will handle the
 * shipment on their side, so ET raises the ask here and Djibouti answers with a
 * name (free text — the officer is not a platform user). Djibouti can send a
 * different name later; the newest one wins and Ethiopia is notified again.
 */
export function TransitAssigneePanel({
  contractId,
  transitAssignee,
  side,
  readOnly = false,
  onChanged,
}: TransitAssigneePanelProps) {
  const [note, setNote] = useState("");
  const [assignee, setAssignee] = useState(transitAssignee?.name ?? "");
  const [changing, setChanging] = useState(false);

  const request = useMutation({
    mutationFn: () => contractsService.requestTransitAssignee(contractId, note.trim()),
    onSuccess: () => {
      toast.success("Request sent to GL Djibouti");
      setNote("");
      onChanged?.();
    },
  });

  const assign = useMutation({
    mutationFn: () =>
      contractsService.assignTransitAssignee(contractId, assignee.trim()),
    onSuccess: () => {
      toast.success("Transit assignee sent to GL Ethiopia");
      setChanging(false);
      onChanged?.();
    },
  });

  const requested = Boolean(transitAssignee?.requestedAt);
  const assigned = Boolean(transitAssignee?.name);

  // Settled state — both desks see the same line; DJ keeps a way to change it.
  if (assigned && !changing) {
    return (
      <Alert
        color="edr-green"
        radius="md"
        icon={<CheckCircle2 size={16} />}
        title="Transit assignee confirmed"
      >
        <Group justify="space-between" wrap="wrap" gap="sm">
          <Text size="sm">
            <Text span fw={700}>
              {transitAssignee!.name}
            </Text>{" "}
            will handle this shipment in transit · assigned{" "}
            {fmt(transitAssignee!.assignedAt)}
          </Text>
          {side === "DJ" && !readOnly ? (
            <Button
              size="compact-xs"
              variant="light"
              radius="md"
              onClick={() => {
                setAssignee(transitAssignee!.name ?? "");
                setChanging(true);
              }}
            >
              Change
            </Button>
          ) : null}
        </Group>
      </Alert>
    );
  }

  // Djibouti's desk: answer the ask.
  if (side === "DJ") {
    if (!requested) {
      return (
        <Alert color="gray" radius="md" icon={<Clock size={16} />}>
          GL Ethiopia has not requested a transit assignee for this clearance yet.
        </Alert>
      );
    }
    return (
      <Paper withBorder radius="md" p="md">
        <Stack gap="sm">
          <Group gap={8}>
            <UserCheck size={16} />
            <Text fw={700} size="sm">
              {changing ? "Change the transit assignee" : "Assign a transit officer"}
            </Text>
            <Badge size="xs" color="orange" variant="light">
              Requested {fmt(transitAssignee?.requestedAt)}
            </Badge>
          </Group>
          {transitAssignee?.requestNote ? (
            <Text size="sm" c="dimmed" style={{ whiteSpace: "pre-wrap" }}>
              GL Ethiopia: {transitAssignee.requestNote}
            </Text>
          ) : null}
          <TextInput
            label="Transit officer"
            description="Name of the person handling this shipment in Djibouti"
            placeholder="e.g. Ahmed Bourhan"
            value={assignee}
            onChange={(e) => setAssignee(e.currentTarget.value)}
            disabled={readOnly}
          />
          <Group justify="flex-end" gap="sm">
            {changing ? (
              <Button variant="default" radius="md" onClick={() => setChanging(false)}>
                Cancel
              </Button>
            ) : null}
            <Button
              color="edr-green"
              radius="md"
              leftSection={<Send size={15} />}
              loading={assign.isPending}
              disabled={readOnly || !assignee.trim()}
              onClick={() => assign.mutate()}
            >
              Send assignment
            </Button>
          </Group>
        </Stack>
      </Paper>
    );
  }

  // Ethiopia's desk: raise the ask, then wait.
  if (requested) {
    return (
      <Alert
        color="orange"
        radius="md"
        icon={<Clock size={16} />}
        title="Waiting for GL Djibouti"
      >
        <Stack gap="sm" align="flex-start">
          <Text size="sm">
            Requested {fmt(transitAssignee?.requestedAt)}. The customs declaration
            opens once Djibouti names the transit officer.
          </Text>
          {!readOnly ? (
            <Button
              size="compact-xs"
              variant="light"
              color="orange"
              radius="md"
              loading={request.isPending}
              onClick={() => request.mutate()}
            >
              Send a reminder
            </Button>
          ) : null}
        </Stack>
      </Alert>
    );
  }

  return (
    <Paper withBorder radius="md" p="md">
      <Stack gap="sm">
        <Group gap={8}>
          <UserCheck size={16} />
          <Text fw={700} size="sm">
            Request a transit assignee
          </Text>
        </Group>
        <Text size="xs" c="dimmed">
          GL Djibouti must name the officer handling this shipment in transit
          before the customs declaration can be filed.
        </Text>
        <Textarea
          label="Note for GL Djibouti (optional)"
          placeholder="Anything they need to know to pick the right officer"
          value={note}
          onChange={(e) => setNote(e.currentTarget.value)}
          autosize
          minRows={2}
          disabled={readOnly}
        />
        <Group justify="flex-end">
          <Button
            color="edr-green"
            radius="md"
            leftSection={<Send size={15} />}
            loading={request.isPending}
            disabled={readOnly}
            onClick={() => request.mutate()}
          >
            Request assignee
          </Button>
        </Group>
      </Stack>
    </Paper>
  );
}

export default TransitAssigneePanel;
