import React, { useEffect, useRef, CSSProperties } from 'react';
import { useAtomValue, useSetAtom } from 'jotai';
import { color, config, Icon, IconButton, Icons } from 'folds';
import { ScreenSize, useScreenSize } from '../../hooks/useScreenSize';
import { toastQueueAtom, dismissToastAtom, ToastNotif } from '../../state/toast';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
import { zIndices } from '../../styles/zIndex';

// Inject the keyframe animation once
const STYLE_ID = 'lotus-toast-keyframes';
function ensureKeyframes() {
  if (document.getElementById(STYLE_ID)) return;
  const style = document.createElement('style');
  style.id = STYLE_ID;
  style.textContent = `
    @keyframes lotusToastIn {
      from { transform: translateX(120%); opacity: 0; }
      to   { transform: translateX(0);    opacity: 1; }
    }
    @media (prefers-reduced-motion: reduce) {
      @keyframes lotusToastIn {
        from { opacity: 0; }
        to   { opacity: 1; }
      }
    }
  `;
  document.head.appendChild(style);
}

type ToastCardProps = {
  toast: ToastNotif;
};

function ToastCard({ toast }: ToastCardProps) {
  const dismiss = useSetAtom(dismissToastAtom);
  // Lotus Terminal (TDS) gets its bespoke glow/accents; every other theme uses
  // folds tokens so toasts render correctly on stock Cinny themes (the --lt-*
  // vars only exist while Terminal mode is active).
  const [lotusTerminal] = useSetting(settingsAtom, 'lotusTerminal');
  const isMobile = useScreenSize() === ScreenSize.Mobile;
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  useEffect(() => {
    if (toast.sticky) return;
    timerRef.current = setTimeout(() => {
      dismiss(toast.id);
    }, 4000);
    return () => {
      if (timerRef.current !== null) clearTimeout(timerRef.current);
    };
  }, [dismiss, toast.id, toast.sticky]);

  const handleCardClick = () => {
    if (toast.onClick) {
      toast.onClick();
    } else {
      // window.location.hash setter auto-prepends '#', so values must not include it
      window.location.hash = toast.hashPath ?? `/room/${toast.roomId}`;
    }
    dismiss(toast.id);
  };

  const handleDismiss = (e: React.MouseEvent) => {
    e.stopPropagation();
    dismiss(toast.id);
  };

  const accent = toast.sticky ? color.Primary.Main : color.Surface.OnContainer;

  const cardStyle: CSSProperties = {
    position: 'relative',
    background: lotusTerminal ? 'var(--lt-bg-card)' : color.Surface.Container,
    border: `${config.borderWidth.B300} solid ${
      lotusTerminal
        ? toast.sticky
          ? 'var(--lt-accent-cyan-border)'
          : 'var(--lt-border-color)'
        : toast.sticky
          ? color.Primary.Main
          : color.Surface.ContainerLine
    }`,
    borderRadius: config.radii.R400,
    padding: `${config.space.S300} ${config.space.S400}`,
    // Full-width on phones (the container spans the viewport there); a fixed
    // 280-340px card would otherwise overflow a narrow screen.
    minWidth: isMobile ? 0 : '280px',
    maxWidth: isMobile ? 'none' : '340px',
    width: isMobile ? '100%' : undefined,
    boxShadow: lotusTerminal
      ? toast.sticky
        ? 'var(--lt-box-glow-cyan)'
        : 'var(--lt-box-glow-orange)'
      : `0 8px 24px ${color.Other.Shadow}`,
    cursor: 'pointer',
    animation: 'lotusToastIn 0.2s ease-out both',
    userSelect: 'none',
  };

  const rowStyle: CSSProperties = {
    display: 'flex',
    alignItems: 'center',
    gap: config.space.S200,
    marginRight: config.space.S500,
  };

  const avatarStyle: CSSProperties = {
    width: '24px',
    height: '24px',
    borderRadius: '50%',
    objectFit: 'cover',
    flexShrink: 0,
  };

  const initialsStyle: CSSProperties = {
    width: '24px',
    height: '24px',
    borderRadius: '50%',
    background: lotusTerminal ? 'var(--lt-accent-orange-dim)' : color.Primary.Container,
    border: `${config.borderWidth.B300} solid ${
      lotusTerminal ? 'var(--lt-accent-orange-border)' : color.Primary.ContainerLine
    }`,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    fontSize: '10px',
    fontWeight: 700,
    color: lotusTerminal ? 'var(--lt-accent-orange)' : color.Primary.OnContainer,
    flexShrink: 0,
  };

  const nameStyle: CSSProperties = {
    color: lotusTerminal
      ? toast.sticky
        ? 'var(--lt-accent-cyan)'
        : 'var(--lt-accent-orange)'
      : accent,
    fontWeight: 600,
    fontSize: '0.85rem',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
  };

  const bodyStyle: CSSProperties = {
    color: lotusTerminal ? 'var(--lt-text-primary)' : color.Surface.OnContainer,
    fontSize: '0.82rem',
    margin: '4px 0 2px',
    overflow: 'hidden',
    ...(toast.sticky
      ? { whiteSpace: 'normal', lineHeight: 1.4 }
      : { textOverflow: 'ellipsis', whiteSpace: 'nowrap' }),
  };

  const roomNameStyle: CSSProperties = {
    color: lotusTerminal ? 'var(--lt-text-secondary)' : color.SurfaceVariant.OnContainer,
    fontSize: '0.75rem',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
  };

  const initials = toast.displayName
    .split(' ')
    .slice(0, 2)
    .map((w) => w[0] ?? '')
    .join('')
    .toUpperCase();

  return (
    <div
      role="button"
      tabIndex={0}
      style={cardStyle}
      onClick={handleCardClick}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') handleCardClick();
      }}
      aria-label={
        toast.roomName
          ? `Notification from ${toast.displayName} in ${toast.roomName}`
          : `${toast.displayName}: ${toast.body}`
      }
    >
      <span style={{ position: 'absolute', top: config.space.S100, right: config.space.S100 }}>
        <IconButton
          type="button"
          size="300"
          radii="300"
          variant="Surface"
          fill="None"
          onClick={handleDismiss}
          aria-label="Dismiss notification"
        >
          <Icon size="100" src={Icons.Cross} />
        </IconButton>
      </span>
      <div style={rowStyle}>
        {toast.iconSrc ? (
          <div style={initialsStyle} aria-hidden="true">
            <Icon size="100" src={toast.iconSrc} />
          </div>
        ) : toast.avatarUrl ? (
          <img src={toast.avatarUrl} alt="" style={avatarStyle} aria-hidden="true" />
        ) : (
          <div style={initialsStyle} aria-hidden="true">
            {initials || '?'}
          </div>
        )}
        <span style={nameStyle}>{toast.displayName}</span>
      </div>
      <div style={bodyStyle}>{toast.body}</div>
      {toast.roomName && <div style={roomNameStyle}>{toast.roomName}</div>}
    </div>
  );
}

export function LotusToastContainer() {
  useEffect(() => {
    ensureKeyframes();
  }, []);

  const toasts = useAtomValue(toastQueueAtom);
  const isMobile = useScreenSize() === ScreenSize.Mobile;
  const listRef = useRef<HTMLDivElement>(null);

  // The newest toast is the last (bottom) child; if the stack ever overflows its
  // max-height (many sticky action toasts), keep that newest one in view instead
  // of leaving it scrolled below the fold.
  useEffect(() => {
    const el = listRef.current;
    if (el) el.scrollTop = el.scrollHeight;
  }, [toasts.length]);

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

  const containerStyle: CSSProperties = {
    position: 'fixed',
    // Span the width just inside the screen edges on a phone (so full-width
    // cards fit); float bottom-right on desktop.
    bottom: isMobile ? config.space.S200 : '1.5rem',
    right: isMobile ? config.space.S200 : '1.5rem',
    left: isMobile ? config.space.S200 : undefined,
    zIndex: zIndices.toast,
    display: 'flex',
    flexDirection: 'column',
    gap: config.space.S200,
    pointerEvents: 'auto',
    // Safety net beyond the queue cap: if many sticky action toasts pile up they
    // scroll within a bounded height instead of covering the whole screen.
    maxHeight: isMobile ? '70vh' : '80vh',
    overflowY: 'auto',
  };

  return (
    <div ref={listRef} style={containerStyle} aria-live="polite" aria-label="Notifications">
      {toasts.map((toast) => (
        <ToastCard key={toast.id} toast={toast} />
      ))}
    </div>
  );
}
