import { useEffect, useRef, useState } from 'react'
import type { SaveStatus } from '../../hooks/useAutoSave'
import { useCompanion, type Mood } from './useCompanion'
import { LottiePlayer } from './LottiePlayer'
import { COMPANIONS, DEFAULT_COMPANION } from './companions'

interface Props {
  wordCount: number
  saveStatus: SaveStatus
  llmDown: boolean
  editTick: number
  acceptTick: number
  text: string
}

// Emoji placeholder per mood, used for any mood a companion has no Lottie for.
const MOOD_EMOJI: Record<Mood, string> = {
  idle: '🐾',
  happy: '😺',
  talking: '😸',
  celebrate: '😻',
  sleeping: '🐾',
}

const STORAGE_KEY = 'petal.companion'

// PetalCompanion is the cozy corner mascot: it watches the writing session via
// useCompanion and shows a Mandarin-first speech bubble for cheers, tips, and
// break reminders. Clicking the mascot opens a picker to switch companions
// (the choice persists in localStorage).
export function PetalCompanion({ wordCount, saveStatus, llmDown, editTick, acceptTick, text }: Props) {
  const { mood, bubble, dismiss, holdBubble, releaseBubble } = useCompanion({
    wordCount,
    saveStatus,
    llmDown,
    editTick,
    acceptTick,
    text,
  })

  const [companionId, setCompanionId] = useState<string>(() => {
    try {
      return localStorage.getItem(STORAGE_KEY) || DEFAULT_COMPANION
    } catch {
      return DEFAULT_COMPANION
    }
  })
  const companion = COMPANIONS.find((c) => c.id === companionId) ?? COMPANIONS[0]
  const [pickerOpen, setPickerOpen] = useState(false)
  const rootRef = useRef<HTMLDivElement>(null)

  // Awake companions (no sleeping clip) don't visibly nap — when the engine
  // dozes them, keep their normal idle pose instead of a sleepy face. Only a
  // mascot with a real sleep animation (the always-asleep cat) shows the zzz.
  const hasSleepClip = Boolean(companion.animations.sleeping)
  // An always-asleep mascot (the cat) stays pinned to one pose so its Lottie
  // never reloads as the engine flips moods underneath it.
  const renderMood: Mood = companion.alwaysAsleep
    ? 'idle'
    : mood === 'sleeping' && !hasSleepClip
      ? 'idle'
      : mood
  const napping = companion.alwaysAsleep || (mood === 'sleeping' && hasSleepClip)

  // Never swap the cute companion for a bare emoji on an idle nap: fall back to
  // the idle animation when a mood has no clip of its own, and only reach for
  // the emoji if the companion ships no animations at all.
  const animationData = companion.animations[renderMood] ?? companion.animations.idle

  function choose(id: string) {
    setCompanionId(id)
    try {
      localStorage.setItem(STORAGE_KEY, id)
    } catch {
      /* private mode / storage disabled — selection just won't persist */
    }
    setPickerOpen(false)
  }

  // Click outside the corner closes the picker.
  useEffect(() => {
    if (!pickerOpen) return
    const onDown = (e: MouseEvent) => {
      if (!rootRef.current?.contains(e.target as Node)) setPickerOpen(false)
    }
    document.addEventListener('mousedown', onDown)
    return () => document.removeEventListener('mousedown', onDown)
  }, [pickerOpen])

  return (
    <div
      ref={rootRef}
      className="pointer-events-none fixed bottom-4 right-4 z-40 flex flex-col items-end gap-2"
    >
      {pickerOpen && (
        <div
          className="petal-bubble pointer-events-auto flex flex-col gap-0.5 p-1.5"
          style={{
            background: 'var(--color-surface)',
            border: '1px solid var(--color-border)',
            borderRadius: 'var(--radius-card)',
            boxShadow: 'var(--shadow-soft)',
            fontFamily: 'var(--font-ui)',
            minWidth: 180,
          }}
        >
          <p
            className="px-2 pb-1 pt-0.5 text-[0.7rem] font-bold"
            style={{ color: 'var(--color-muted)' }}
          >
            选个小伙伴 · Choose a companion
          </p>
          {COMPANIONS.map((c) => {
            const active = c.id === companion.id
            return (
              <button
                key={c.id}
                type="button"
                onClick={() => choose(c.id)}
                className="flex items-center gap-2.5 rounded-xl px-2 py-1.5 text-left text-sm transition-colors"
                style={{
                  background: active ? 'var(--color-surface-alt)' : 'transparent',
                  color: 'var(--color-plum)',
                }}
                onMouseEnter={(e) => {
                  if (!active) e.currentTarget.style.background = 'var(--color-surface-alt)'
                }}
                onMouseLeave={(e) => {
                  if (!active) e.currentTarget.style.background = 'transparent'
                }}
              >
                <span style={{ fontSize: 20, lineHeight: 1 }}>{c.emoji}</span>
                <span className="flex-1">
                  <span className="font-bold">{c.zh}</span>{' '}
                  <span style={{ color: 'var(--color-muted)' }}>{c.name}</span>
                </span>
                {active && <span style={{ color: 'var(--color-accent)' }}>✓</span>}
              </button>
            )
          })}
        </div>
      )}

      {bubble && !pickerOpen && (
        <div
          role="status"
          onClick={dismiss}
          onMouseEnter={holdBubble}
          onMouseLeave={releaseBubble}
          className="petal-bubble pointer-events-auto max-w-[420px] cursor-pointer p-4 pr-5"
          style={{
            background: 'var(--color-surface)',
            border: '1px solid var(--color-border)',
            borderRadius: 'var(--radius-card)',
            boxShadow: 'var(--shadow-soft)',
            // CJK-first font stack (north star Note #17) — she reads Mandarin.
            fontFamily: 'var(--font-ui)',
          }}
          title="Click to dismiss"
        >
          <p
            className="font-bold leading-snug"
            style={{ color: 'var(--color-plum)', fontSize: '1.4rem' }}
          >
            {bubble.zh}
          </p>
          <p
            className="mt-0.5 leading-snug"
            style={{ color: 'var(--color-muted)', fontSize: '1.15rem' }}
          >
            {bubble.en}
          </p>
        </div>
      )}

      <button
        type="button"
        onClick={() => setPickerOpen((o) => !o)}
        title="Choose a companion"
        aria-label="Choose a companion"
        className={`petal-companion pointer-events-auto select-none ${napping ? 'petal-companion-sleep' : ''}`}
        style={{
          // Size scales with the viewport — see --petal-companion-size in index.css.
          width: 'var(--petal-companion-size)',
          height: 'var(--petal-companion-size)',
          padding: 0,
          borderRadius: 'var(--radius-pill)',
          background: 'var(--color-surface-alt)',
          border: '1px solid var(--color-border)',
          boxShadow: 'var(--shadow-soft)',
          display: 'grid',
          placeItems: 'center',
          position: 'relative',
        }}
      >
        <LottiePlayer
          key={companion.id}
          animationData={animationData}
          flip={companion.flip}
          className="petal-companion-art"
          fallback={
            <span style={{ fontSize: 'calc(var(--petal-companion-size) * 0.5)', lineHeight: 1 }}>
              {MOOD_EMOJI[renderMood]}
            </span>
          }
        />
        {napping && (
          <span className="petal-zzz absolute" aria-hidden style={{ color: 'var(--color-muted)' }}>
            z
          </span>
        )}
      </button>
    </div>
  )
}
