'use client';

import { X } from 'lucide-react';
import type { CSSProperties, ReactNode } from 'react';

import { Avatar, AvatarFallback, AvatarImage } from '@djangocfg/ui-core/components';
import { cn } from '@djangocfg/ui-core/lib';

import { Z_INDEX } from '../constants';
import type { ChatMessage, ChatPersona } from '../types';
import type { ChatFABPosition } from './ChatFAB';
import { useChatPresence } from './useChatPresence';

export interface ChatUnreadPreviewProps {
  /** Controlled — usually `!dockOpen && !!message`. */
  open: boolean;
  /** Inbound message to preview. `null` hides the bubble. */
  message: ChatMessage | null;
  /** Tap → open chat + mark read. */
  onClick?: () => void;
  /** × → mark read without opening. */
  onDismiss?: () => void;
  /** Anchor corner — match the FAB so the bubble sits above it. @default 'bottom-right' */
  position?: ChatFABPosition;
  /** Horizontal offset from screen edge, matches the FAB. @default 24 */
  fabOffset?: number;
  /** Vertical clearance above/below the FAB. @default 96 */
  fabClearance?: number;
  /** Lines of body text before ellipsis. @default 2 */
  truncate?: number;
  /** z-index. @default 99 — companion tier, just below the open dock. */
  zIndex?: number;
  /** Render in-place (stories / previews). @default false */
  inline?: boolean;
  /** Override classes on the bubble. */
  className?: string;
  /** Override styles on the bubble. */
  style?: CSSProperties;
  /** ARIA label for the dismiss button. @default 'Mark as read' */
  dismissLabel?: string;
  /** Override the avatar — defaults to derived from `message.sender`. */
  avatar?: ReactNode;
  /** Override the sender label — defaults to `message.sender?.name`. */
  senderName?: string;
}

const TIME_FORMAT = new Intl.DateTimeFormat(undefined, {
  hour: '2-digit',
  minute: '2-digit',
});

function anchorStyle(
  position: ChatFABPosition,
  fabOffset: number,
  fabClearance: number,
): CSSProperties {
  const [vert, horiz] = position.split('-') as ['bottom' | 'top', 'right' | 'left'];
  return { [vert]: fabClearance, [horiz]: fabOffset } as CSSProperties;
}

function originClass(position: ChatFABPosition): string {
  if (position === 'bottom-right') return 'origin-bottom-right';
  if (position === 'bottom-left') return 'origin-bottom-left';
  if (position === 'top-right') return 'origin-top-right';
  return 'origin-top-left';
}

function deriveAvatar(persona?: ChatPersona, name?: string): ReactNode {
  const initials =
    persona?.initials ??
    (name ?? persona?.name ?? '?')
      .split(/\s+/)
      .map((p) => p[0])
      .filter(Boolean)
      .slice(0, 2)
      .join('')
      .toUpperCase();
  return (
    <Avatar className="h-9 w-9">
      {persona?.avatarUrl ? <AvatarImage src={persona.avatarUrl} /> : null}
      <AvatarFallback>{initials || '?'}</AvatarFallback>
    </Avatar>
  );
}

/**
 * Push-notification bubble next to the chat FAB.
 *
 * Shows the last inbound message while the chat is closed —
 * Intercom / LiveChat-style. Tap → open chat (host wires `onClick`).
 * Dismiss × → keep chat closed but stop nagging.
 *
 * Pair with `useChatUnread()` (inside `<ChatProvider>`) for state.
 */
export function ChatUnreadPreview({
  open,
  message,
  onClick,
  onDismiss,
  position = 'bottom-right',
  fabOffset = 24,
  fabClearance = 96,
  truncate = 2,
  zIndex = Z_INDEX.companion,
  inline = false,
  className,
  style,
  dismissLabel = 'Mark as read',
  avatar,
  senderName,
}: ChatUnreadPreviewProps) {
  const shouldShow = open && !!message;
  const phase = useChatPresence(shouldShow, 200);
  if (phase === 'hidden' || !message) return null;

  const animating = phase === 'entering' || phase === 'leaving';
  const clickable = !!onClick;
  const displayName = senderName ?? message.sender?.name ?? 'New message';
  const stamp = TIME_FORMAT.format(new Date(message.createdAt));

  return (
    <div
      role={clickable ? 'button' : 'status'}
      aria-live="polite"
      tabIndex={clickable ? 0 : -1}
      onClick={clickable ? onClick : undefined}
      onKeyDown={
        clickable
          ? (e) => {
              if (e.key === 'Enter' || e.key === ' ') {
                e.preventDefault();
                onClick?.();
              }
            }
          : undefined
      }
      className={cn(
        inline ? 'relative inline-flex' : 'fixed',
        'flex items-start gap-2.5 max-w-[300px]',
        'rounded-2xl border border-border bg-popover text-popover-foreground',
        'px-3.5 py-2.5 shadow-2xl transition-all duration-200 ease-out',
        clickable &&
          'cursor-pointer hover:bg-accent/40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',
        originClass(position),
        animating ? 'opacity-0 scale-95 translate-y-1' : 'opacity-100 scale-100 translate-y-0',
        className,
      )}
      style={{
        ...(inline ? {} : anchorStyle(position, fabOffset, fabClearance)),
        ...(inline ? {} : { zIndex }),
        pointerEvents: phase === 'visible' ? 'auto' : 'none',
        ...style,
      }}
    >
      <div className="mt-0.5 shrink-0">
        {avatar ?? deriveAvatar(message.sender, displayName)}
      </div>

      <div className="min-w-0 flex-1 text-sm leading-snug">
        <div className="flex items-baseline justify-between gap-2">
          <div className="truncate text-[12px] font-semibold text-foreground">
            {displayName}
          </div>
          <div className="shrink-0 text-[10px] text-muted-foreground">{stamp}</div>
        </div>
        <div
          className="text-foreground/90 mt-0.5 break-words"
          style={{
            display: '-webkit-box',
            WebkitLineClamp: truncate,
            WebkitBoxOrient: 'vertical',
            overflow: 'hidden',
          }}
        >
          {message.content}
        </div>
      </div>

      {onDismiss ? (
        <button
          type="button"
          aria-label={dismissLabel}
          onClick={(e) => {
            e.stopPropagation();
            onDismiss();
          }}
          className={cn(
            '-mr-1 -mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded-full',
            'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground',
            'focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',
          )}
        >
          <X className="h-3.5 w-3.5" />
        </button>
      ) : null}
    </div>
  );
}
