import {
  ActionIcon,
  Badge,
  Button,
  Group,
  Popover,
  Stack,
  Text,
  Tooltip,
} from "@mantine/core";
import { DateTimePicker } from "@mantine/dates";
import { useMutation } from "@tanstack/react-query";
import { Pencil, PlayCircle, StopCircle } from "lucide-react";
import { useEffect, useState } from "react";

import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";
import { useToast } from "@/hooks/use-toast";
import { api } from "@/services/api";
import type { StationWorkPhaseLog } from "@/types/trainScheduling";

const parseError = (error: unknown, fallback: string) => {
  const message = (error as { response?: { data?: { message?: string | string[] } } })
    ?.response?.data?.message;
  if (Array.isArray(message)) return message.join("; ");
  return message || (error as Error)?.message || fallback;
};

const fmtTime = (iso: string) => {
  const d = new Date(iso);
  return Number.isNaN(d.getTime()) ? iso : d.toLocaleString();
};

const fmtElapsed = (fromIso: string, toIso?: string | null) => {
  const from = new Date(fromIso).getTime();
  const to = toIso ? new Date(toIso).getTime() : Date.now();
  const mins = Math.max(0, Math.round((to - from) / 60_000));
  const h = Math.floor(mins / 60);
  const m = mins % 60;
  return h > 0 ? `${h}h ${m}m` : `${m}m`;
};

/** Pencil-popover to correct an already-recorded start/end timestamp. */
function EditTimeButton({
  label,
  value,
  disabled,
  disabledReason,
  minDate,
  maxDate,
  onSave,
  saving,
}: {
  label: string;
  value: string;
  disabled: boolean;
  disabledReason: string;
  minDate?: Date;
  maxDate?: Date;
  onSave: (at: Date) => void;
  saving: boolean;
}) {
  const [opened, setOpened] = useState(false);
  const [draft, setDraft] = useState<Date | null>(null);
  useEffect(() => {
    if (opened) setDraft(new Date(value));
  }, [opened, value]);

  return (
    <Popover opened={opened} onChange={setOpened} withArrow shadow="md" position="bottom">
      <Popover.Target>
        <Tooltip label={disabled ? disabledReason : `Correct the ${label} time`}>
          <ActionIcon
            size="xs"
            variant="subtle"
            color="gray"
            disabled={disabled}
            onClick={() => setOpened((o) => !o)}
          >
            <Pencil size={12} />
          </ActionIcon>
        </Tooltip>
      </Popover.Target>
      <Popover.Dropdown>
        <Stack gap="xs">
          <DateTimePicker
            label={`Correct ${label} time`}
            value={draft}
            onChange={(v) => setDraft(v ? new Date(v) : null)}
            minDate={minDate}
            maxDate={maxDate ?? new Date()}
            valueFormat="DD MMM YYYY HH:mm"
            clearable={false}
            radius="md"
            maw={280}
          />
          <Group justify="flex-end" gap="xs">
            <Button size="compact-xs" variant="default" onClick={() => setOpened(false)}>
              Cancel
            </Button>
            <Button
              size="compact-xs"
              loading={saving}
              disabled={!draft}
              onClick={() => {
                if (draft) {
                  onSave(draft);
                  setOpened(false);
                }
              }}
            >
              Save
            </Button>
          </Group>
        </Stack>
      </Popover.Dropdown>
    </Popover>
  );
}

/**
 * Start/End buttons + elapsed time for one station's loading OR unloading
 * window. Booking load/unload at the yard is server-gated on the window having
 * been started, so these buttons come first in the operator's flow. Each of
 * the four buttons (start/end × loading/unloading) is its own permission, and
 * the pencil edits a recorded time under the same permission that set it.
 */
export function StationWorkControls({
  scheduleId,
  yardId,
  phase,
  log,
}: {
  scheduleId: string;
  yardId: string;
  phase: "loading" | "unloading";
  log?: StationWorkPhaseLog | null;
}) {
  const { user } = useAuth();
  const { toast } = useToast();
  const canStart = hasPermission(
    user,
    phase === "loading"
      ? FREIGHT_PERMS.trainScheduling.loadingStart
      : FREIGHT_PERMS.trainScheduling.unloadingStart,
  );
  const canEnd = hasPermission(
    user,
    phase === "loading"
      ? FREIGHT_PERMS.trainScheduling.loadingEnd
      : FREIGHT_PERMS.trainScheduling.unloadingEnd,
  );

  const record = useMutation(api.trainScheduling.recordStationWork.mutationOptions());

  // Re-render each minute so the running elapsed time ticks while unended.
  const [, setTick] = useState(0);
  useEffect(() => {
    if (!log?.startedAt || log?.endedAt) return;
    const t = setInterval(() => setTick((n) => n + 1), 60_000);
    return () => clearInterval(t);
  }, [log?.startedAt, log?.endedAt]);

  const doRecord = (edge: "start" | "end", at?: Date) => {
    record.mutate(
      { scheduleId, yardId, phase, edge, ...(at ? { at: at.toISOString() } : {}) },
      {
        onSuccess: () =>
          toast({
            title: `${phase === "loading" ? "Loading" : "Unloading"} ${edge} recorded`,
          }),
        onError: (err) =>
          toast({
            title: `Could not record ${phase} ${edge}`,
            description: parseError(err, "Please try again"),
            variant: "destructive",
          }),
      },
    );
  };

  const title = phase === "loading" ? "Loading" : "Unloading";
  const started = Boolean(log?.startedAt);
  const ended = Boolean(log?.endedAt);

  return (
    <Group gap="sm" wrap="wrap" align="center">
      <Badge variant="light" color={ended ? "gray" : started ? "edr-green" : "yellow"} radius="sm">
        {title}
        {ended ? " done" : started ? " in progress" : " not started"}
      </Badge>

      {!started ? (
        <Tooltip
          label={
            canStart
              ? `Record the moment ${phase} work begins at this station`
              : `You don't have permission to start ${phase}`
          }
        >
          <Button
            size="compact-sm"
            variant="light"
            color="edr-green"
            leftSection={<PlayCircle size={14} />}
            disabled={!canStart}
            loading={record.isPending}
            onClick={() => doRecord("start")}
          >
            Start {phase}
          </Button>
        </Tooltip>
      ) : (
        <>
          <Group gap={4} wrap="nowrap">
            <Text size="xs" c="dimmed">
              {fmtTime(log!.startedAt!)} → {ended ? fmtTime(log!.endedAt!) : "…"} (
              {fmtElapsed(log!.startedAt!, log?.endedAt)})
            </Text>
            {log?.startedByName || log?.endedByName ? (
              <Tooltip
                label={[
                  log?.startedByName ? `Started by ${log.startedByName}` : null,
                  log?.endedByName ? `Ended by ${log.endedByName}` : null,
                ]
                  .filter(Boolean)
                  .join(" · ")}
              >
                <Badge size="xs" variant="light" color="gray" radius="sm">
                  {log?.endedByName ?? log?.startedByName}
                </Badge>
              </Tooltip>
            ) : null}
            <EditTimeButton
              label={`${phase} start`}
              value={log!.startedAt!}
              disabled={!canStart}
              disabledReason={`You don't have permission to edit the ${phase} start`}
              maxDate={log?.endedAt ? new Date(log.endedAt) : new Date()}
              onSave={(at) => doRecord("start", at)}
              saving={record.isPending}
            />
            {ended ? (
              <EditTimeButton
                label={`${phase} end`}
                value={log!.endedAt!}
                disabled={!canEnd}
                disabledReason={`You don't have permission to edit the ${phase} end`}
                minDate={new Date(log!.startedAt!)}
                onSave={(at) => doRecord("end", at)}
                saving={record.isPending}
              />
            ) : null}
          </Group>
          {!ended ? (
            <Tooltip
              label={
                canEnd
                  ? `Record the moment ${phase} work is finished at this station`
                  : `You don't have permission to end ${phase}`
              }
            >
              <Button
                size="compact-sm"
                variant="light"
                color="orange"
                leftSection={<StopCircle size={14} />}
                disabled={!canEnd}
                loading={record.isPending}
                onClick={() => doRecord("end")}
              >
                End {phase}
              </Button>
            </Tooltip>
          ) : null}
        </>
      )}
    </Group>
  );
}
