import {
  Alert,
  Badge,
  Button,
  Card,
  Group,
  Stack,
  Text,
} from "@mantine/core";
import { IconAlertTriangle, IconLogin2, IconLogout2 } from "@tabler/icons-react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";

import { apiErrorMessage } from "@/auth/http";
import { checkIn, checkOut, getToday } from "../api";
import { AttendanceStatusBadge, formatMinutes, formatTime } from "./AttendanceStatusBadge";

/**
 * Clock in and out.
 *
 * The button offered is derived from today's record rather than from a local
 * flag: a page reload, a second tab or a punch from the door reader must all
 * lead to the same state, and a client-side "have I clocked in?" would disagree
 * with the server the moment any of those happened.
 */
export function ClockWidget() {
  const queryClient = useQueryClient();
  const [now, setNow] = useState(new Date());
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const timer = window.setInterval(() => setNow(new Date()), 30_000);
    return () => window.clearInterval(timer);
  }, []);

  const today = useQuery({ queryKey: ["attendance-today"], queryFn: getToday });

  const invalidate = () => {
    queryClient.invalidateQueries({ queryKey: ["attendance-today"] });
    queryClient.invalidateQueries({ queryKey: ["my-attendance"] });
    queryClient.invalidateQueries({ queryKey: ["attendance-summary"] });
  };

  const punchIn = useMutation({
    mutationFn: () => checkIn(),
    onSuccess: () => { invalidate(); setError(null); },
    onError: (err) => setError(apiErrorMessage(err)),
  });

  const punchOut = useMutation({
    mutationFn: () => checkOut(),
    onSuccess: () => { invalidate(); setError(null); },
    onError: (err) => setError(apiErrorMessage(err)),
  });

  const record = today.data;
  const clockedIn = Boolean(record?.checkIn && !record?.checkOut);
  const done = Boolean(record?.checkIn && record?.checkOut);

  return (
    <Card withBorder radius="md" padding="lg">
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Stack gap={2}>
          <Text size="xs" c="dimmed">
            {now.toLocaleDateString(undefined, {
              weekday: "long",
              day: "numeric",
              month: "long",
            })}
          </Text>
          <Text size="2rem" fw={700} lh={1.1}>
            {now.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
          </Text>
          <Group gap="xs" mt={6}>
            {record && <AttendanceStatusBadge status={record.status} />}
            {record?.isRegularized && (
              <Badge size="sm" variant="light" color="gray">
                corrected
              </Badge>
            )}
          </Group>
        </Stack>

        <Stack gap="xs" align="flex-end">
          {!done && (
            <Button
              size="md"
              color={clockedIn ? "red" : "blue"}
              leftSection={
                clockedIn ? <IconLogout2 size={18} /> : <IconLogin2 size={18} />
              }
              loading={punchIn.isPending || punchOut.isPending}
              onClick={() => (clockedIn ? punchOut.mutate() : punchIn.mutate())}
              data-testid={clockedIn ? "attendance-clock-out" : "attendance-clock-in"}
            >
              {clockedIn ? "Clock out" : "Clock in"}
            </Button>
          )}
          {done && (
            <Text size="sm" c="dimmed">
              Done for today
            </Text>
          )}
          {record?.checkIn && (
            <Text size="xs" c="dimmed">
              In {formatTime(record.checkIn)}
              {record.checkOut && ` · Out ${formatTime(record.checkOut)}`}
            </Text>
          )}
          {record?.workedMinutes ? (
            <Text size="xs" c="dimmed">
              {formatMinutes(record.workedMinutes)} worked
              {record.lateMinutes > 0 &&
                ` · ${formatMinutes(record.lateMinutes)} late`}
            </Text>
          ) : null}
        </Stack>
      </Group>

      {error && (
        <Alert color="red" mt="md" variant="light" icon={<IconAlertTriangle size={18} />}>
          {error}
        </Alert>
      )}
    </Card>
  );
}
