import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useAtom } from 'jotai';
import { Box, Button, Icon, IconButton, Icons, Text, color, config } from 'folds';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { scheduledMessagesAtom, ScheduledMessage } from '../../state/scheduledMessages';
import { cancelScheduledMessage } from '../../utils/scheduledMessages';

interface ScheduledMessagesTrayProps {
  roomId: string;
}

function formatSendAt(sendAt: number): string {
  const date = new Date(sendAt);
  const now = new Date();
  const isToday =
    date.getFullYear() === now.getFullYear() &&
    date.getMonth() === now.getMonth() &&
    date.getDate() === now.getDate();
  const tomorrow = new Date(now);
  tomorrow.setDate(tomorrow.getDate() + 1);
  const isTomorrow =
    date.getFullYear() === tomorrow.getFullYear() &&
    date.getMonth() === tomorrow.getMonth() &&
    date.getDate() === tomorrow.getDate();
  const timeStr = date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
  if (isToday) return `Today ${timeStr}`;
  if (isTomorrow) return `Tomorrow ${timeStr}`;
  return `${date.toLocaleDateString()} ${timeStr}`;
}

export function ScheduledMessagesTray({ roomId }: ScheduledMessagesTrayProps) {
  const mx = useMatrixClient();
  const [scheduledMessages, setScheduledMessages] = useAtom(scheduledMessagesAtom);
  const [expanded, setExpanded] = useState(false);
  const [cancelling, setCancelling] = useState<Set<string>>(new Set());

  const messages = useMemo(() => scheduledMessages.get(roomId) ?? [], [scheduledMessages, roomId]);

  // Remove scheduled messages whose time has passed
  useEffect(() => {
    if (messages.length === 0) return undefined;

    const nearestSendAt = Math.min(...messages.map((m) => m.sendAt));
    const delay = nearestSendAt - Date.now();

    const timer = setTimeout(
      () => {
        const now = Date.now();
        setScheduledMessages((prev) => {
          const next = new Map(prev);
          const current = next.get(roomId) ?? [];
          const remaining = current.filter((m) => m.sendAt > now);
          if (remaining.length === 0) {
            next.delete(roomId);
          } else {
            next.set(roomId, remaining);
          }
          return next;
        });
      },
      Math.max(0, delay) + 2000,
    ); // 2s grace after scheduled time

    return () => clearTimeout(timer);
  }, [messages, roomId, setScheduledMessages]);

  const handleCancel = useCallback(
    async (msg: ScheduledMessage) => {
      if (cancelling.has(msg.delayId)) return;
      setCancelling((prev) => new Set(prev).add(msg.delayId));
      try {
        await cancelScheduledMessage(mx, msg.delayId);
      } catch {
        // If cancellation fails on the server, still remove locally
        // since the user intends to remove it
      } finally {
        setScheduledMessages((prev) => {
          const next = new Map(prev);
          const current = next.get(roomId) ?? [];
          const remaining = current.filter((m) => m.delayId !== msg.delayId);
          if (remaining.length === 0) {
            next.delete(roomId);
          } else {
            next.set(roomId, remaining);
          }
          return next;
        });
        setCancelling((prev) => {
          const next = new Set(prev);
          next.delete(msg.delayId);
          return next;
        });
      }
    },
    [mx, roomId, cancelling, setScheduledMessages],
  );

  if (messages.length === 0) return null;

  return (
    <Box
      direction="Column"
      style={{
        borderBottom: `${config.borderWidth.B300} solid ${color.SurfaceVariant.ContainerLine}`,
        background: color.SurfaceVariant.Container,
      }}
    >
      {/* Tray header */}
      <Button
        variant="Secondary"
        fill="None"
        radii="0"
        onClick={() => setExpanded((v) => !v)}
        aria-expanded={expanded}
        aria-label={`${messages.length} scheduled message${messages.length !== 1 ? 's' : ''}`}
        before={<Icon src={Icons.Clock} size="50" />}
        after={<Icon src={expanded ? Icons.ChevronTop : Icons.ChevronBottom} size="50" />}
        style={{
          padding: `${config.space.S100} ${config.space.S300}`,
          justifyContent: 'flex-start',
        }}
      >
        <Text size="T200" style={{ flex: 1, fontWeight: 600, textAlign: 'left' }}>
          {messages.length} scheduled message{messages.length !== 1 ? 's' : ''}
        </Text>
      </Button>

      {/* Tray items */}
      {expanded && (
        <Box direction="Column">
          {messages.map((msg) => (
            <Box
              key={msg.delayId}
              alignItems="Center"
              gap="200"
              style={{
                padding: `${config.space.S100} ${config.space.S300}`,
                borderTop: `${config.borderWidth.B300} solid ${color.SurfaceVariant.ContainerLine}`,
              }}
            >
              <Text
                size="T200"
                priority="400"
                style={{
                  flex: 1,
                  overflow: 'hidden',
                  textOverflow: 'ellipsis',
                  whiteSpace: 'nowrap',
                }}
              >
                {typeof msg.content.body === 'string' ? (msg.content.body as string) : '(message)'}
              </Text>
              <Text size="T200" priority="300" style={{ whiteSpace: 'nowrap', flexShrink: 0 }}>
                {formatSendAt(msg.sendAt)}
              </Text>
              <IconButton
                size="300"
                radii="300"
                variant="SurfaceVariant"
                aria-label="Cancel scheduled message"
                disabled={cancelling.has(msg.delayId)}
                onClick={(e) => {
                  e.stopPropagation();
                  handleCancel(msg);
                }}
              >
                <Icon src={Icons.Cross} size="50" />
              </IconButton>
            </Box>
          ))}
        </Box>
      )}
    </Box>
  );
}
