import type { ReactNode } from 'react';

import type { ChatContextValue } from '../context';
import type { ChatDockPrefs } from '../hooks/useChatDockPrefs';

/**
 * Declarative reset slot. The launcher renders the standard
 * `<ChatHeaderResetButton>` wired to `onReset`, defaulting `onSuccess`
 * to `ctx.clearMessages()`. The button hides itself until a `sessionId`
 * exists on the chat context.
 */
export interface ChatHeaderResetSlot {
  /** Backend reset call. Resolves to `true` on success. */
  onReset: () => Promise<boolean>;
  /** Show a confirm dialog before calling `onReset`. @default true */
  confirm?: boolean;
  /** Confirm dialog title. */
  confirmTitle?: string;
  /** Confirm dialog message. */
  confirmMessage?: string;
  /** Override tooltip / aria label. */
  ariaLabel?: string;
  /**
   * Called after a successful reset. Defaults to `ctx.clearMessages()`.
   * Override to also re-fetch history, navigate, fire analytics, etc.
   */
  onSuccess?: (ctx: ChatContextValue) => void;
  /** Called on failure (returned `false` or threw). */
  onError?: (err?: unknown) => void;
}

/** Declarative language-picker slot. */
export interface ChatHeaderLanguageSlot {
  /** Subset of BCP-47 tags to offer. */
  allowedTags?: string[];
  /** Override aria-label. */
  ariaLabel?: string;
  /** Hide the globe fallback icon when no flag resolves. */
  hideFallbackIcon?: boolean;
}

/**
 * Declarative mode-toggle slot. The launcher owns `useChatDockPrefs`
 * internally — set `persistAs` to a localStorage key for persistence
 * (omit for ephemeral / session-only mode toggling).
 */
export interface ChatHeaderModeToggleSlot {
  /**
   * localStorage key for `useChatDockPrefs`. When provided the toggle
   * persists across reloads; omit to use an ephemeral in-memory toggle.
   */
  persistAs?: string;
  /** Override the default `{ mode: 'popover', side: 'right', sideWidth: 420 }`. */
  defaults?: Partial<ChatDockPrefs>;
  /** Show the toggle even on viewports below `lg` (1024px). @default true */
  forceVisible?: boolean;
  /** Tooltip / aria for popover → side. */
  expandLabel?: string;
  /** Tooltip / aria for side → popover. */
  collapseLabel?: string;
}

/**
 * Header buttons rendered INSIDE the `<ChatProvider>` mounted by
 * `<ChatLauncher>`. Each entry is rendered in the fixed order:
 *
 *   custom · languagePicker · modeToggle · audio · reset
 *
 * (close icon is always last, owned by `<ChatHeader>`).
 *
 * Slots that accept `boolean | object`:
 *  - `true`  → render with default config
 *  - `false` → hide explicitly
 *  - object  → render with the given options
 *
 * Defaults:
 *  - `audio`: rendered automatically when `audio` prop is passed to
 *    `<ChatLauncher>` AND the resolved instance is not silent.
 *  - `modeToggle`, `languagePicker`: off unless opted in.
 *  - `reset`: off unless `onReset` is provided.
 */
export interface ChatHeaderSlots {
  /** Auto-mute toggle. Defaults to true when launcher `audio` is configured. */
  audio?: boolean;
  /** Popover ↔ side mode toggle. */
  modeToggle?: boolean | ChatHeaderModeToggleSlot;
  /** Speech-recognition language picker. */
  languagePicker?: boolean | ChatHeaderLanguageSlot;
  /** Reset-conversation button. */
  reset?: ChatHeaderResetSlot;
  /** Arbitrary extra buttons rendered first (left-most). */
  custom?: (ctx: ChatContextValue) => ReactNode;
}

/**
 * Resolved mode-toggle config used by the launcher to pick between
 * the dock's mode/side props and the prefs slot.
 */
export interface ResolvedChatHeaderSlots {
  audio: boolean;
  modeToggle: ChatHeaderModeToggleSlot | null;
  languagePicker: ChatHeaderLanguageSlot | null;
  reset: ChatHeaderResetSlot | null;
  custom: ((ctx: ChatContextValue) => ReactNode) | null;
}

export function resolveHeaderSlots(
  slots: ChatHeaderSlots | undefined,
  audioConfigured: boolean,
): ResolvedChatHeaderSlots {
  const s = slots ?? {};
  const audio = s.audio ?? audioConfigured;
  const modeToggle: ChatHeaderModeToggleSlot | null =
    s.modeToggle === true
      ? {}
      : s.modeToggle && typeof s.modeToggle === 'object'
        ? s.modeToggle
        : null;
  const languagePicker: ChatHeaderLanguageSlot | null =
    s.languagePicker === true
      ? {}
      : s.languagePicker && typeof s.languagePicker === 'object'
        ? s.languagePicker
        : null;
  return {
    audio,
    modeToggle,
    languagePicker,
    reset: s.reset ?? null,
    custom: s.custom ?? null,
  };
}
