'use client'

import * as React from 'react'
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Pencil, Plus, RefreshCw, Trash2 } from 'lucide-react'
import { cn } from '../../lib/utils'
import { SlideCanvas } from './SlideCanvas'
import { SlideFilmstrip } from './SlideFilmstrip'
import type { SlideData } from './types'

export interface SlideDeckViewerProps {
  slides: SlideData[]
  /** Controlled active slide id. Omit for uncontrolled (defaults to first). */
  activeId?: string
  onActiveChange?: (id: string) => void
  /** Regenerate the currently-active slide. */
  onRegenerate?: (slide: SlideData) => void
  /** Delete the currently-active slide. Shows a delete control when provided. */
  onDelete?: (slide: SlideData) => void
  /** Move the active slide one position left/right. Shows move controls when provided. */
  onMove?: (slide: SlideData, direction: 'left' | 'right') => void
  /** Insert a blank slide after the active one. Shows an add control when provided. */
  onInsert?: (afterSlide: SlideData) => void
  /** Edit the active slide's title/content (then it regenerates). Shows an edit control. */
  onEdit?: (slide: SlideData, edits: { title?: string; content?: string }) => void
  /** Drag-to-reorder in the filmstrip: source + target 0-based indices. */
  onReorder?: (fromIndex: number, toIndex: number) => void
  emptyState?: React.ReactNode
  /** Extra actions rendered in the stage toolbar (e.g. approve / edit). */
  toolbarActions?: (slide: SlideData) => React.ReactNode
  renderStructured?: (slide: SlideData) => React.ReactNode
  className?: string
}

/**
 * Google-Slides-style deck viewer: a large active-slide stage with prev/next +
 * regenerate controls, a position indicator, and a thumbnail filmstrip.
 * Keyboard arrows navigate. App-agnostic — `present-web` supplies the slides.
 */
export function SlideDeckViewer({
  slides,
  activeId,
  onActiveChange,
  onRegenerate,
  onDelete,
  onMove,
  onInsert,
  onEdit,
  onReorder,
  emptyState,
  toolbarActions,
  renderStructured,
  className,
}: SlideDeckViewerProps) {
  const isControlled = activeId !== undefined
  const [internalId, setInternalId] = React.useState<string | undefined>(slides[0]?.id)

  const currentId = isControlled ? activeId : internalId
  const index = Math.max(0, slides.findIndex((s) => s.id === currentId))
  const active = slides[index]

  // Inline edit of the active slide's title/content.
  const [editing, setEditing] = React.useState(false)
  const [editTitle, setEditTitle] = React.useState('')
  const [editContent, setEditContent] = React.useState('')
  const openEditor = () => {
    setEditTitle(active?.title ?? '')
    setEditContent(active?.content ?? '')
    setEditing(true)
  }
  const saveEdit = () => {
    if (active) onEdit?.(active, { title: editTitle, content: editContent })
    setEditing(false)
  }

  const goTo = React.useCallback(
    (i: number) => {
      const clamped = Math.min(slides.length - 1, Math.max(0, i))
      const next = slides[clamped]
      if (!next) return
      if (!isControlled) setInternalId(next.id)
      onActiveChange?.(next.id)
    },
    [slides, isControlled, onActiveChange]
  )

  // Global ←/→ navigation: works without first focusing the stage, but stays
  // out of the way of text entry — when the user is typing in the chat composer
  // (or any input/textarea/contenteditable) or holding a modifier, the arrows
  // belong to the cursor, not the deck.
  React.useEffect(() => {
    function onKey(e: KeyboardEvent) {
      if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return
      if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return
      const t = e.target as HTMLElement | null
      const tag = t?.tagName
      if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || t?.isContentEditable) {
        return
      }
      e.preventDefault()
      goTo(e.key === 'ArrowRight' ? index + 1 : index - 1)
    }
    window.addEventListener('keydown', onKey)
    return () => window.removeEventListener('keydown', onKey)
  }, [goTo, index])

  if (slides.length === 0) {
    return (
      <div className={cn('flex h-full items-center justify-center p-6 text-center text-muted-foreground', className)}>
        {emptyState ?? 'No slides yet.'}
      </div>
    )
  }

  return (
    <div className={cn('flex h-full min-h-0 flex-col bg-muted/20', className)}>
      {/* Stage toolbar */}
      <div className="flex shrink-0 items-center justify-between gap-2 border-b border-border bg-background/60 px-3 py-2">
        <div className="flex items-center gap-1">
          <button
            type="button"
            onClick={() => goTo(index - 1)}
            disabled={index === 0}
            aria-label="Previous slide"
            className="rounded p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30"
          >
            <ChevronLeft className="h-4 w-4" aria-hidden="true" />
          </button>
          <span className="min-w-14 text-center text-sm font-medium tabular-nums">
            {index + 1} / {slides.length}
          </span>
          <button
            type="button"
            onClick={() => goTo(index + 1)}
            disabled={index === slides.length - 1}
            aria-label="Next slide"
            className="rounded p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-30"
          >
            <ChevronRight className="h-4 w-4" aria-hidden="true" />
          </button>
        </div>
        <div className="flex items-center gap-2">
          {onMove && active && slides.length > 1 && (
            <div className="flex items-center gap-1">
              <button
                type="button"
                onClick={() => onMove(active, 'left')}
                disabled={index === 0}
                aria-label={`Move slide ${active.slideNumber} left`}
                className="rounded-md border border-input bg-background p-1.5 shadow-sm hover:bg-accent disabled:opacity-30"
              >
                <ChevronsLeft className="h-4 w-4" aria-hidden="true" />
              </button>
              <button
                type="button"
                onClick={() => onMove(active, 'right')}
                disabled={index === slides.length - 1}
                aria-label={`Move slide ${active.slideNumber} right`}
                className="rounded-md border border-input bg-background p-1.5 shadow-sm hover:bg-accent disabled:opacity-30"
              >
                <ChevronsRight className="h-4 w-4" aria-hidden="true" />
              </button>
            </div>
          )}
          {onInsert && active && (
            <button
              type="button"
              onClick={() => onInsert(active)}
              aria-label="Add a slide"
              className="inline-flex items-center gap-1.5 rounded-md border border-input bg-background px-2.5 py-1.5 text-sm shadow-sm hover:bg-accent"
            >
              <Plus className="h-3.5 w-3.5" aria-hidden="true" /> Add
            </button>
          )}
          {onEdit && active && (
            <button
              type="button"
              onClick={openEditor}
              aria-label={`Edit slide ${active.slideNumber}`}
              className="inline-flex items-center gap-1.5 rounded-md border border-input bg-background px-2.5 py-1.5 text-sm shadow-sm hover:bg-accent"
            >
              <Pencil className="h-3.5 w-3.5" aria-hidden="true" /> Edit
            </button>
          )}
          {active && toolbarActions?.(active)}
          {onRegenerate && active && (
            <button
              type="button"
              onClick={() => onRegenerate(active)}
              className="inline-flex items-center gap-1.5 rounded-md border border-input bg-background px-2.5 py-1.5 text-sm shadow-sm hover:bg-accent"
            >
              <RefreshCw className="h-3.5 w-3.5" aria-hidden="true" /> Regenerate
            </button>
          )}
          {onDelete && active && slides.length > 1 && (
            <button
              type="button"
              onClick={() => onDelete(active)}
              aria-label={`Delete slide ${active.slideNumber}`}
              className="inline-flex items-center gap-1.5 rounded-md border border-input bg-background px-2.5 py-1.5 text-sm text-red-600 shadow-sm hover:bg-red-50"
            >
              <Trash2 className="h-3.5 w-3.5" aria-hidden="true" /> Delete
            </button>
          )}
        </div>
      </div>

      {/* Stage */}
      <div
        className="relative flex min-h-0 flex-1 items-center justify-center overflow-hidden p-4 focus:outline-none"
        data-testid="slide-deck-stage"
        tabIndex={0}
        role="group"
        aria-label={`Slide ${index + 1} of ${slides.length}`}
      >
        {active && (
          <SlideCanvas
            slide={active}
            onRetry={onRegenerate ? () => onRegenerate(active) : undefined}
            renderStructured={renderStructured}
          />
        )}
        {editing && active && (
          <div
            className="absolute inset-0 z-10 flex items-center justify-center bg-background/70 p-4"
            data-testid="slide-editor"
          >
            <div className="w-full max-w-lg rounded-lg border border-border bg-background p-4 shadow-lg">
              <h3 className="text-sm font-semibold">Edit slide {active.slideNumber}</h3>
              <label className="mt-3 block text-xs font-medium text-muted-foreground">Title</label>
              <input
                value={editTitle}
                onChange={(e) => setEditTitle(e.target.value)}
                aria-label="Slide title"
                className="mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
              />
              <label className="mt-3 block text-xs font-medium text-muted-foreground">Content</label>
              <textarea
                value={editContent}
                onChange={(e) => setEditContent(e.target.value)}
                rows={5}
                aria-label="Slide content"
                className="mt-1 w-full resize-y rounded-md border border-input bg-background px-3 py-2 text-sm"
              />
              <div className="mt-3 flex justify-end gap-2">
                <button
                  type="button"
                  onClick={() => setEditing(false)}
                  className="rounded-md border border-input bg-background px-3 py-1.5 text-sm shadow-sm hover:bg-accent"
                >
                  Cancel
                </button>
                <button
                  type="button"
                  onClick={saveEdit}
                  className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground shadow-sm hover:opacity-90"
                >
                  Save &amp; regenerate
                </button>
              </div>
            </div>
          </div>
        )}
      </div>

      {/* Filmstrip */}
      <div className="shrink-0 border-t border-border bg-background/60">
        <SlideFilmstrip
          slides={slides}
          activeId={currentId}
          onSelect={(id) => goTo(slides.findIndex((s) => s.id === id))}
          onReorder={onReorder}
        />
      </div>
    </div>
  )
}
