import styled from '@emotion/styled';
import { useEffect, useState } from 'react';

import StudioContext from '@/components/studio/StudioContext';
import { useContextSelector } from '@/hooks/useContextSelector';
import ctrlStr from '@/utils/ctrlStr';

const Container = styled.div<{ visible?: boolean }>`
  position: absolute;
  z-index: 1000;
  bottom: 120px;
  left: 50%;
  transform: translate(-50%, 100%);
  background-color: var(--color-background-secondary);
  color: var(--color-foreground-primary);
  padding: 8px 16px;
  border-radius: 4px;
  font-size: 18px;
  opacity: 0;
  transition:
    transform 0.3s ease-out,
    opacity 0.3s ease-out;
  ${({ visible }) =>
    visible &&
    `
    transform: translate(-50%, 0);
    opacity: 1;
  `}
`;

export function HintMessage() {
  const inFlightDrags = useContextSelector(
    StudioContext,
    (ctx) => ctx.inFlightDrags
  );
  const isPreviewing = useContextSelector(
    StudioContext,
    (ctx) =>
      !!ctx.previewController.previewPackage &&
      ctx.previewController.previewingOnTimeline
  );
  const replacingLyrics = useContextSelector(
    StudioContext,
    (ctx) => ctx.lyricsEditController.replacingLyrics
  );
  const [message, setMessage] = useState<string | null>(null);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    let newMessage: string | null = null;

    if (inFlightDrags.hasMatching((key) => key.startsWith('selectionEdge'))) {
      newMessage = `Hold [${ctrlStr}] to disable snap-to-grid`;
    } else if (isPreviewing) {
      newMessage = 'Previewing a change. Press [ESC] to stop.';
    } else if (replacingLyrics) {
      newMessage = 'Replacing lyrics. Press [ESC] to stop.';
    }

    let showTimer: NodeJS.Timeout;
    let hideTimer: NodeJS.Timeout;

    if (newMessage) {
      setMessage(newMessage);
      // trigger slide-up
      showTimer = setTimeout(() => setVisible(true), 100);
    } else {
      setVisible(false);
      // Allow hide animation to complete before removing message
      hideTimer = setTimeout(() => setMessage(null), 300);
    }
    return () => {
      clearTimeout(showTimer);
      clearTimeout(hideTimer);
    };
  }, [inFlightDrags, isPreviewing, replacingLyrics]); // Track the full inFlightDrags object to detect selection-edge changes

  if (!message) return null;
  return <Container visible={visible}>{message}</Container>;
}
