import React, { useCallback, useEffect, useState } from 'react'
import { useCloseOnWClick } from '../../hooks/useCloseOnWClick'
import { useInventoryContext } from '../../context/InventoryContext'
import { useScale } from '../../context/ScaleContext'
import { getInventoryType } from '../../registry'
import { InventoryWindow } from '../InventoryWindow'
import { CursorItem } from '../CursorItem'
import { JEI } from '../JEI'
import type { JEIItem } from '../JEI'
import { Notes } from '../Notes'
import type { Note } from '../Notes'
import { RecipeInventoryView } from '../RecipeGuide'
import type { RecipeGuide, RecipeNavFrame } from '../../types'

export interface InventoryOverlayProps {
  type: string
  title?: string
  /**
   * Extra properties forwarded to InventoryWindow. For the 'hotbar' type these
   * control special features: `showOffhand` (1/0) and `container` (1/0).
   */
  properties?: Record<string, number>
  /** Hide semi-transparent backdrop behind inventory */
  noBackdrop?: boolean
  /** Backdrop color (default: 'rgba(0,0,0,0.5)') */
  backdropColor?: string
  /** Called when clicking outside the inventory (or pressing Esc) */
  onClose?: () => void
  /** Show JEI sidebar */
  showJEI?: boolean
  jeiItems?: JEIItem[]
  jeiPosition?: 'left' | 'right'
  jeiOnGetRecipes?: (item: JEIItem) => RecipeGuide[]
  jeiOnGetUsages?: (item: JEIItem) => RecipeGuide[]
  jeiOnItemClick?: (item: JEIItem) => void
  jeiOnItemRightClick?: (item: JEIItem) => void
  /** Enable Notes sidebar (uses localStorage by default if callbacks not provided) */
  enableNotes?: boolean
  /** Callback to get notes. If not provided and enableNotes is true, uses localStorage. */
  notesOnGet?: () => Note[] | Promise<Note[]>
  /** Callback to save notes. If not provided and enableNotes is true, uses localStorage. */
  notesOnSave?: (notes: Note[]) => void | Promise<void>
  /** Storage key for localStorage (default: 'mc-inv-notes') */
  notesStorageKey?: string
  /**
   * Content shown in the left side-panel area (e.g. custom panels).
   * Width is auto-computed as (overlayWidth - inventoryWidth) / 2 - padding.
   * Note: If enableNotes is true, Notes will be shown in addition to leftPanel.
   */
  leftPanel?: React.ReactNode
  className?: string
  style?: React.CSSProperties
  children?: React.ReactNode
  /** Show yellow debug border around the overlay area */
  debugBounds?: boolean
  /** Show red debug outline around the inventory background */
  showDebug?: boolean
  /** When true, entity display area shows layout debug bounds instead of the default image. */
  entityDisplayDebug?: boolean
  /** Override entity display rendering. Pass a function returning JSX, or null to hide. */
  renderEntity?: ((width: number, height: number) => React.ReactNode) | null
  /** Hide the "INV" version watermark (opt-out) */
  noWatermark?: boolean
  /** Called when the gear button is clicked. When provided, a small settings gear appears in the overlay. */
  onOpenSettings?: () => void
}

export function InventoryOverlay({
  type,
  title,
  properties,
  noBackdrop = false,
  backdropColor = 'rgba(0,0,0,0.5)',
  onClose,
  showJEI = false,
  jeiItems = [],
  jeiPosition = 'right',
  jeiOnGetRecipes,
  jeiOnGetUsages,
  jeiOnItemClick,
  jeiOnItemRightClick,
  enableNotes = false,
  notesOnGet,
  notesOnSave,
  notesStorageKey,
  leftPanel,
  className,
  style,
  children,
  debugBounds = false,
  showDebug = false,
  entityDisplayDebug = false,
  renderEntity,
  noWatermark = false,
  onOpenSettings,
}: InventoryOverlayProps) {
  const { heldItem, sendAction, setHeldItem, focusedSlot, setFocusedSlot, hoveredSlot, getSlot } = useInventoryContext()
  const { scale } = useScale()
  const [settingsHovered, setSettingsHovered] = useState(false)

  useCloseOnWClick(onClose)

  const def = getInventoryType(type)
  const invUnscaledW = def?.backgroundWidth ?? 176
  const sideGapPx = 5 * scale // gap from overlay edge and from inventory edge

  // Full height for side panels = overlay height minus edge gaps
  const sidePanelHeight = `calc(100% - ${sideGapPx * 2}px)`

  // Recipe navigation stack — when non-empty, RecipeInventoryView replaces InventoryWindow
  const [recipeNavStack, setRecipeNavStack] = useState<RecipeNavFrame[]>([])

  const pushRecipeFrame = useCallback((frame: RecipeNavFrame) => {
    setRecipeNavStack((s) => [...s, frame])
  }, [])

  const popRecipeFrame = useCallback(() => {
    setRecipeNavStack((s) => s.slice(0, -1))
  }, [])

  const handleGuideIndexChange = useCallback((idx: number) => {
    setRecipeNavStack((s) => {
      const next = [...s]
      next[next.length - 1] = { ...next[next.length - 1], guideIndex: idx }
      return next
    })
  }, [])

  // Called by RecipeInventoryView when R/U is pressed over a recipe ingredient
  const handleRecipePushFrame = useCallback((item: RecipeNavFrame['item'], mode: 'recipes' | 'usages') => {
    const getter = mode === 'recipes' ? jeiOnGetRecipes : jeiOnGetUsages
    if (!getter) return
    const jeiItem: JEIItem = { type: item.type, name: item.name, displayName: item.displayName, count: item.count, metadata: item.metadata }
    const guides = getter(jeiItem)
    if (guides.length === 0) return
    pushRecipeFrame({ item, mode, guides, guideIndex: 0 })
  }, [jeiOnGetRecipes, jeiOnGetUsages, pushRecipeFrame])

  // R / U while hovering a regular inventory slot (not JEI, not recipe view)
  useEffect(() => {
    if (!jeiOnGetRecipes && !jeiOnGetUsages) return
    const handler = (e: KeyboardEvent) => {
      if (e.code !== 'KeyR' && e.code !== 'KeyU') return
      const target = e.target as Element | null
      const tagName = (target as { tagName?: string })?.tagName ?? ''
      if (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT' || (target as { isContentEditable?: boolean })?.isContentEditable) return
      if (recipeNavStack.length > 0) return // RecipeInventoryView handles its own R/U
      if (hoveredSlot === null || hoveredSlot < 0) return // JEI slots handled by JEI.tsx
      const slot = getSlot(hoveredSlot)
      if (!slot?.item) return
      const item = slot.item
      handleRecipePushFrame(
        { type: item.type, name: item.name ?? '', displayName: item.displayName ?? item.name ?? `Item #${item.type}`, count: item.count, metadata: item.metadata },
        e.code === 'KeyR' ? 'recipes' : 'usages',
      )
    }
    window.addEventListener('keydown', handler)
    return () => window.removeEventListener('keydown', handler)
  }, [jeiOnGetRecipes, jeiOnGetUsages, recipeNavStack.length, hoveredSlot, getSlot, handleRecipePushFrame])

  // Fires for any click that isn't stopped by an interactive panel (inventory, hotbar, JEI, etc.)
  const handleBackdropClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
    // Only handle left (drop all) and right (drop one) mouse buttons
    if (e.button !== 0 && e.button !== 2) return
    if (heldItem) {
      const dropAll = e.button === 0 // LMB = drop all, RMB = drop one
      sendAction({ type: 'drop', slotIndex: -1, all: dropAll })
      if (dropAll) {
        setHeldItem(null)
      } else {
        // Right click: drop one, keep rest on cursor
        if (heldItem.count > 1) {
          setHeldItem({ ...heldItem, count: heldItem.count - 1 })
        } else {
          setHeldItem(null)
        }
      }
      // Also clear focused slot if any
      if (focusedSlot !== null) setFocusedSlot(null)
    } else if (focusedSlot !== null) {
      setFocusedSlot(null)
    } else {
      onClose?.()
    }
  }, [heldItem, sendAction, setHeldItem, onClose, focusedSlot, setFocusedSlot])

  const jeiPanel = showJEI ? (
    <JEI
      items={jeiItems}
      position={jeiPosition}
      onItemClick={jeiOnItemClick}
      onItemRightClick={jeiOnItemRightClick}
      onGetRecipes={jeiOnGetRecipes}
      onGetUsages={jeiOnGetUsages}
      onPushRecipeFrame={pushRecipeFrame}
    />
  ) : null

  const notesPanel = enableNotes ? (
    <Notes
      onGetNotes={notesOnGet}
      onSaveNotes={notesOnSave}
      storageKey={notesStorageKey}
    />
  ) : null

  // Full height side panels; width fills the space between overlay edge and inventory center
  const sidePanelBase: React.CSSProperties = {
    position: 'absolute',
    top: sideGapPx,
    bottom: sideGapPx,
    width: `calc(100% / 2 - ${invUnscaledW * scale}px / 2 - ${sideGapPx}px * 2)`,
    height: sidePanelHeight,
    zIndex: 5,
    display: 'flex',
    flexDirection: 'column',
  }

  return (
    <>
      <div
        className={['mc-inv-overlay', className].filter(Boolean).join(' ')}
        onMouseDown={handleBackdropClick}
        onContextMenu={(e) => e.preventDefault()}
        style={{
          position: 'absolute',
          inset: 0,
          width: '100%',
          height: '100%',
          background: noBackdrop ? 'transparent' : backdropColor,
          cursor: 'default',
          zIndex: 1,
          ...style,
        }}
      >
        {/* ── Left side panel (leftPanel prop, Notes, and/or JEI-left) ── */}
        {(leftPanel || enableNotes || (showJEI && jeiPosition === 'left')) && (
          <div
            className="mc-inv-overlay-side mc-inv-overlay-side-left"
            style={{ ...sidePanelBase, left: sideGapPx, pointerEvents: 'auto' }}
          >
            {enableNotes && (
              <div className="mc-inv-overlay-notes" style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
                {notesPanel}
              </div>
            )}
            {leftPanel && (
              <div
                onClick={(e) => e.stopPropagation()}
                style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}
              >
                {leftPanel}
              </div>
            )}
            {showJEI && jeiPosition === 'left' && (
              <div
                className="mc-inv-overlay-jei mc-inv-overlay-jei-left"
                onMouseDown={(e) => e.stopPropagation()}
                onClick={(e) => e.stopPropagation()}
                style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', width: '100%' }}
              >
                {jeiPanel}
              </div>
            )}
          </div>
        )}

        {/* ── Inventory centered anchor — flex centering, no transform ── */}
        <div
          className="mc-inv-overlay-center"
          style={{
            position: 'absolute',
            inset: 0,
            width: '100%',
            height: '100%',
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            pointerEvents: 'none',
          }}
        >
          <div className="mc-inv-overlay-content" style={{ position: 'relative', pointerEvents: 'auto' }}>
            {/* Inventory / Recipe view — clicks clear focused slot; slots stop propagation themselves */}
            <div
              className="mc-inv-overlay-window"
              onMouseDown={(e) => e.stopPropagation()}
              onClick={(e) => {
                e.stopPropagation()
                // Clicking the inventory background (not a slot) clears focused slot
                if (focusedSlot !== null) setFocusedSlot(null)
              }}
            >
              {recipeNavStack.length > 0 ? (
                <RecipeInventoryView
                  navStack={recipeNavStack}
                  onBack={popRecipeFrame}
                  onGuideIndexChange={handleGuideIndexChange}
                  onPushFrame={handleRecipePushFrame}
                />
              ) : (
                <InventoryWindow
                  type={type}
                  title={title}
                  properties={properties}
                  showDebug={showDebug}
                  entityDisplayDebug={entityDisplayDebug}
                  renderEntity={renderEntity}
                />
              )}
            </div>
          </div>
        </div>

        {/* ── Right side panel (JEI-right) ── */}
        {showJEI && jeiPosition === 'right' && (
          <div
            className="mc-inv-overlay-side mc-inv-overlay-side-right"
            onMouseDown={(e) => e.stopPropagation()}
            onClick={(e) => e.stopPropagation()}
            style={{ ...sidePanelBase, right: sideGapPx, pointerEvents: 'auto' }}
          >
            <div
              className="mc-inv-overlay-jei mc-inv-overlay-jei-right"
              style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', width: '100%' }}
            >
              {jeiPanel}
            </div>
          </div>
        )}

        {/* Extra children (overlay-level) */}
        {children}

        {/* Watermark */}
        {!noWatermark && (
          <a
            className="mc-inv-watermark"
            href="https://www.npmjs.com/package/minecraft-inventory"
            target="_blank"
            rel="noopener noreferrer"
            onMouseDown={(e) => e.stopPropagation()}
            onClick={(e) => e.stopPropagation()}
            style={{
              position: 'absolute',
              top: 4,
              left: 4,
              fontSize: 9,
              fontFamily: "'Minecraftia', 'Minecraft', monospace",
              color: 'rgba(255,255,255,0.3)',
              textDecoration: 'none',
              pointerEvents: 'auto',
              zIndex: 1,
              lineHeight: 1,
            }}
          >
            INV 0.1.45
          </a>
        )}

        {/* Settings gear button */}
        {onOpenSettings && (
          <button
            className="mc-inv-settings-btn"
            onClick={(e) => { e.stopPropagation(); onOpenSettings() }}
            onMouseDown={(e) => e.stopPropagation()}
            onMouseEnter={() => setSettingsHovered(true)}
            onMouseLeave={() => setSettingsHovered(false)}
            title="Settings"
            style={{
              position: 'absolute',
              top: 4,
              right: 4,
              background: 'none',
              border: 'none',
              padding: 2,
              cursor: 'pointer',
              color: settingsHovered ? 'rgba(255,255,255,0.8)' : 'rgba(255,255,255,0.35)',
              pointerEvents: 'auto',
              zIndex: 2,
              lineHeight: 1,
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
            }}
          >
            <svg viewBox="0 0 20 20" width={14} height={14} fill="currentColor">
              <path d="M8.5 0h3l.5 2.5 1.3.5L15.5 1.5l2.1 2.1-1.5 2.2.5 1.3L19.1 8v3l-2.5.5-.5 1.3 1.5 2.2-2.1 2.1-2.2-1.5-1.3.5L11.5 19h-3L8 16.5l-1.3-.5L4.5 17.5l-2.1-2.1 1.5-2.2L3.4 12 .9 11.5v-3L3.4 8l.5-1.3L2.4 4.5 4.5 2.4l2.2 1.5L8 3.4 8.5 0zM10 6.5a3.5 3.5 0 100 7 3.5 3.5 0 000-7z"/>
            </svg>
          </button>
        )}

        {/* Debug bounds */}
        {debugBounds && (
          <div
            className="mc-inv-overlay-debug-marker"
            style={{
              position: 'absolute',
              inset: 0,
              border: '2px solid yellow',
              pointerEvents: 'none',
              boxSizing: 'border-box',
            }}
          />
        )}
      </div>

      <CursorItem />
    </>
  )
}
