import {
  Alert,
  Button,
  Group,
  Modal,
  NumberInput,
  Select,
  Stack,
  Text,
  Textarea,
} from "@mantine/core";
import { useMutation, useQuery } from "@tanstack/react-query";
import { AlertTriangle, Send, XCircle } from "lucide-react";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";

import { api } from "@/services/api";
import type { WagonTransferRequest } from "@/services/wagon.service";

import { outstandingOn, wagonTypeLabel, yardLabel } from "./wagon-transfer-ui";

/** Yard + wagon-type option lists, shared by both modals. */
function useTransferOptions(enabled: boolean) {
  const { data: yards = [] } = useQuery({
    ...api.routes.yards.queryOptions({ staleTime: 5 * 60_000 }),
    enabled,
  });
  const { data: wagonTypes = [] } = useQuery({
    ...api.wagonTypes.list.queryOptions(),
    enabled,
  });
  return {
    yardOptions: yards.map((y) => ({
      value: y.id,
      label: y.label ?? y.code ?? y.id,
    })),
    typeOptions: wagonTypes.map((t) => ({
      value: t.id,
      label: [t.code, t.name].filter(Boolean).join(" · "),
    })),
  };
}

export interface TransferRequestFormModalProps {
  opened: boolean;
  onClose: () => void;
  /**
   * Carry-over from a request that could not be met in full: the destination,
   * type, outstanding count and reason are pre-filled and the user only picks
   * WHICH other yard to ask. Undefined for a plain new request.
   */
  prefillFrom?: WagonTransferRequest | null;
  onCreated?: () => void;
}

/**
 * File a wagon-transfer request. The count is deliberately NOT capped by what
 * the source yard holds today — OCC fulfils in instalments, so asking for 50
 * where 20 sit is a normal request.
 */
export function TransferRequestFormModal({
  opened,
  onClose,
  prefillFrom,
  onCreated,
}: TransferRequestFormModalProps) {
  const { yardOptions, typeOptions } = useTransferOptions(opened);
  const [fromYardId, setFromYardId] = useState<string | null>(null);
  const [toYardId, setToYardId] = useState<string | null>(null);
  const [wagonTypeId, setWagonTypeId] = useState<string | null>(null);
  const [quantity, setQuantity] = useState<number | string>(1);
  const [reason, setReason] = useState("");

  // Re-seed on every open so a carry-over never leaks into the next request.
  useEffect(() => {
    if (!opened) return;
    setFromYardId(null); // always chosen fresh — that is the point of a re-ask
    setToYardId(prefillFrom?.toYardId ?? null);
    setWagonTypeId(prefillFrom?.wagonTypeId ?? null);
    setQuantity(prefillFrom ? outstandingOn(prefillFrom) : 1);
    setReason(prefillFrom?.reason ?? "");
  }, [opened, prefillFrom]);

  const create = useMutation(api.wagonTransferRequests.create.mutationOptions());

  const sameYard = Boolean(fromYardId && fromYardId === toYardId);
  const valid =
    Boolean(fromYardId && toYardId && wagonTypeId && reason.trim()) &&
    !sameYard &&
    Number(quantity) >= 1;

  const submit = async () => {
    if (!valid) return;
    try {
      await create.mutateAsync({
        fromYardId: fromYardId!,
        toYardId: toYardId!,
        wagonTypeId: wagonTypeId!,
        quantity: Number(quantity),
        reason: reason.trim(),
      });
      toast.success("Transfer request filed");
      onClose();
      onCreated?.();
    } catch {
      // Server reason is surfaced by the http interceptor.
    }
  };

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      radius="md"
      size="md"
      title={prefillFrom ? "Request the rest from another yard" : "New transfer request"}
    >
      <Stack gap="sm">
        {prefillFrom ? (
          <Alert color="orange" radius="md" icon={<AlertTriangle size={15} />}>
            {yardLabel(prefillFrom.fromYard)} supplied{" "}
            {prefillFrom.fulfilledQuantity} of {prefillFrom.quantity}. Pick
            another yard to cover the remaining {outstandingOn(prefillFrom)}.
          </Alert>
        ) : null}

        <Select
          label="Source yard"
          description={prefillFrom ? "Which yard should supply the rest" : undefined}
          placeholder="Where the wagons come from"
          data={yardOptions}
          value={fromYardId}
          onChange={setFromYardId}
          searchable
          required
          error={sameYard ? "Source and destination must differ" : undefined}
        />
        <Select
          label="Destination yard"
          placeholder="Where they are needed"
          data={yardOptions}
          value={toYardId}
          onChange={setToYardId}
          searchable
          required
        />
        <Select
          label="Wagon type"
          placeholder="Type of wagon"
          data={typeOptions}
          value={wagonTypeId}
          onChange={setWagonTypeId}
          searchable
          required
        />
        <NumberInput
          label="How many"
          description="Can exceed what the yard holds today — OCC delivers in instalments"
          min={1}
          value={quantity}
          onChange={setQuantity}
          required
        />
        <Textarea
          label="Reason"
          placeholder="Why the wagons are needed"
          value={reason}
          onChange={(e) => setReason(e.currentTarget.value)}
          autosize
          minRows={2}
          required
        />

        <Group justify="flex-end" gap="sm">
          <Button variant="default" radius="md" onClick={onClose}>
            Cancel
          </Button>
          <Button
            color="edr-green"
            radius="md"
            leftSection={<Send size={15} />}
            loading={create.isPending}
            disabled={!valid}
            onClick={() => void submit()}
          >
            File request
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

export interface TransferCloseShortModalProps {
  request: WagonTransferRequest | null;
  onClose: () => void;
  onClosed?: (request: WagonTransferRequest) => void;
}

/**
 * End a request the source yard cannot finish. What already moved stays moved;
 * the requester is notified of the shortfall so they can raise it elsewhere.
 */
export function TransferCloseShortModal({
  request,
  onClose,
  onClosed,
}: TransferCloseShortModalProps) {
  const [note, setNote] = useState("");
  const closeShort = useMutation(
    api.wagonTransferRequests.closeShort.mutationOptions(),
  );

  useEffect(() => {
    if (request) setNote("");
  }, [request]);

  const submit = async () => {
    if (!request) return;
    try {
      await closeShort.mutateAsync({ id: request.id, note: note.trim() || undefined });
      toast.success("Request closed — the requester has been notified");
      onClose();
      onClosed?.(request);
    } catch {
      // Server reason surfaced by the http interceptor.
    }
  };

  const outstanding = request ? outstandingOn(request) : 0;

  return (
    <Modal
      opened={Boolean(request)}
      onClose={onClose}
      radius="md"
      title="Close this request short"
    >
      {!request ? null : (
        <Stack gap="sm">
          <Text size="sm">
            {yardLabel(request.fromYard)} → {yardLabel(request.toYard)} ·{" "}
            {wagonTypeLabel(request.wagonType)}
          </Text>
          <Alert color="orange" radius="md" icon={<AlertTriangle size={15} />}>
            {request.fulfilledQuantity} of {request.quantity} wagon(s) have been
            supplied. Closing leaves {outstanding} undelivered — the requester is
            told to ask another yard.
          </Alert>
          <Textarea
            label="Why can't the yard supply the rest?"
            description="Included in the requester's notification"
            value={note}
            onChange={(e) => setNote(e.currentTarget.value)}
            autosize
            minRows={2}
          />
          <Group justify="flex-end" gap="sm">
            <Button variant="default" radius="md" onClick={onClose}>
              Keep it open
            </Button>
            <Button
              color="orange"
              radius="md"
              leftSection={<XCircle size={15} />}
              loading={closeShort.isPending}
              onClick={() => void submit()}
            >
              Close short
            </Button>
          </Group>
        </Stack>
      )}
    </Modal>
  );
}
