'use client';

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

import { cn } from '@djangocfg/ui-core/lib';

import { Z_INDEX } from '../constants';
import { useChatPresence } from './useChatPresence';
import type { ChatFABPosition } from './ChatFAB';

export interface ChatGreetingProps {
  /** Controlled visibility — usually `!chatOpen && !userDismissed`. */
  open: boolean;
  /** Greeting text. Pass a string for the default bubble, or any ReactNode. */
  children: ReactNode;
  /** Click handler — typically opens the chat. Bubble is clickable when set. */
  onClick?: () => void;
  /** Close (×) button handler — typically marks the greeting as dismissed. */
  onDismiss?: () => void;
  /** Anchor relative to a FAB on the same side. @default 'bottom-right' */
  position?: ChatFABPosition;
  /**
   * Horizontal pixel offset matching the FAB's `offset` prop, so the greeting
   * lines up under the FAB. @default 24
   */
  fabOffset?: number;
  /**
   * Vertical pixel offset above/below the FAB centerline. @default 96
   * (room for an `md` FAB plus a small gap).
   */
  fabClearance?: number;
  /** Delay before the greeting appears, in ms. @default 1500 */
  delayMs?: number;
  /** z-index. @default 99 — companion tier, just below the open dock. */
  zIndex?: number;
  /** Override classes on the bubble. */
  className?: string;
  /** Override styles on the bubble. */
  style?: CSSProperties;
  /** Optional sender avatar / icon shown on the left. */
  avatar?: ReactNode;
  /** Optional sender label rendered above the text. */
  senderName?: string;
  /** ARIA label for the dismiss button. @default 'Dismiss' */
  dismissLabel?: string;
  /**
   * Render in-place (no fixed positioning). Useful for stories and inline previews.
   * @default false
   */
  inline?: boolean;
}

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 {
  // Scale-in origin matches the corner the bubble attaches to.
  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';
}

/**
 * Greeting bubble shown next to a `ChatFAB` to invite the user to start a
 * conversation (LiveChat / Intercom-style proactive prompt).
 *
 * Renders fixed-position, anchored to the same corner as the FAB. Owns its
 * own delayed-mount + presence animation. Hide on chat open and/or after
 * user dismissal.
 *
 * @example
 * ```tsx
 * const [open, setOpen] = useState(false);
 * const [dismissed, setDismissed] = useState(false);
 *
 * <ChatLauncher
 *   open={open}
 *   onOpenChange={setOpen}
 *   fab={{ variant: 'animated' }}
 *   dock={{ title: 'Support' }}
 * >
 *   <SupportChat />
 * </ChatLauncher>
 *
 * <ChatGreeting
 *   open={!open && !dismissed}
 *   onClick={() => setOpen(true)}
 *   onDismiss={() => setDismissed(true)}
 *   senderName="Anna from Support"
 *   delayMs={2000}
 * >
 *   Hi! 👋 Got a question? I'm here to help.
 * </ChatGreeting>
 * ```
 */
export function ChatGreeting({
  open,
  children,
  onClick,
  onDismiss,
  position = 'bottom-right',
  fabOffset = 24,
  fabClearance = 96,
  delayMs = 1500,
  zIndex = Z_INDEX.companion,
  className,
  style,
  avatar,
  senderName,
  dismissLabel = 'Dismiss',
  inline = false,
}: ChatGreetingProps) {
  const [delayed, setDelayed] = useState(delayMs <= 0);

  useEffect(() => {
    if (!open || delayMs <= 0) return;
    const t = setTimeout(() => setDelayed(true), delayMs);
    return () => clearTimeout(t);
  }, [open, delayMs]);

  const shouldShow = open && delayed;
  const phase = useChatPresence(shouldShow, 220);

  if (phase === 'hidden') return null;

  const animating = phase === 'entering' || phase === 'leaving';
  const clickable = !!onClick;

  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-[280px]',
        '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,
      }}
    >
      {avatar && <div className="mt-0.5 shrink-0">{avatar}</div>}

      <div className="min-w-0 flex-1 text-sm leading-snug">
        {senderName && (
          <div className="mb-0.5 text-[11px] font-medium text-muted-foreground">
            {senderName}
          </div>
        )}
        <div className="text-foreground">{children}</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>
      )}
    </div>
  );
}
