import { useMemo, useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { Plus, Star, Trash2, X } from '../../lib/icons'
import { useDiary, type DiaryEntry } from '../../stores/diary-store'

interface Props {
  itemId: string
  itemName: string
}

const QUICK_EMOJI = ['🎬', '🍿', '😢', '😱', '🤯', '😴', '❤️', '🤩', '🤔', '😂', '👀', '🔥']

/**
 * Per-item diary log. Shows chronological entries for this item with
 * optional rating + emoji + note, plus a "Log a watch" button that
 * opens an inline editor for a new entry.
 *
 * Editing works in-place with a small drawer below each entry.
 */
export default function DiarySection({ itemId, itemName }: Props) {
  // Select the whole array; filter + sort in render via useMemo.
  // A selector that returns .filter()/.sort() output creates a new
  // reference each call and trips useSyncExternalStore's loop guard.
  const allEntries = useDiary(s => s.entries)
  const add = useDiary(s => s.add)
  const remove = useDiary(s => s.remove)
  const [composing, setComposing] = useState(false)
  const sorted = useMemo(
    () =>
      allEntries
        .filter(e => e.itemId === itemId)
        .sort((a, b) => b.watchedAt.localeCompare(a.watchedAt)),
    [allEntries, itemId],
  )

  function startCompose() {
    setComposing(true)
  }

  function commitNew(payload: { rating?: number; note?: string; emoji?: string; rewatch?: boolean }) {
    add({ itemId, itemName, ...payload })
    setComposing(false)
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between gap-3">
        <p className="text-[12.5px] text-text-3 leading-relaxed">
          {sorted.length === 0
            ? "You haven't logged a watch yet for this item."
            : `${sorted.length} ${sorted.length === 1 ? 'entry' : 'entries'}`}
        </p>
        <button
          onClick={startCompose}
          className="inline-flex items-center gap-1.5 h-8 px-3 rounded-full bg-accent text-void text-[12px] font-semibold tracking-tight hover:bg-accent-hover transition focus-ring"
        >
          <Plus size={12} stroke={2.5} />
          Log a watch
        </button>
      </div>

      <AnimatePresence>
        {composing && (
          <motion.div
            initial={{ opacity: 0, y: -4 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -4 }}
            transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}
          >
            <Composer onCancel={() => setComposing(false)} onSave={commitNew} />
          </motion.div>
        )}
      </AnimatePresence>

      {sorted.length > 0 && (
        <ol className="space-y-2 mt-1">
          {sorted.map(entry => (
            <DiaryRow key={entry.id} entry={entry} onRemove={() => remove(entry.id)} />
          ))}
        </ol>
      )}
    </div>
  )
}

function Composer({
  onCancel,
  onSave,
}: {
  onCancel: () => void
  onSave: (payload: { rating?: number; note?: string; emoji?: string; rewatch?: boolean }) => void
}) {
  const [rating, setRating] = useState(0)
  const [note, setNote] = useState('')
  const [emoji, setEmoji] = useState<string | undefined>(undefined)
  const [rewatch, setRewatch] = useState(false)
  return (
    <div className="rounded-xl bg-elevated/40 ring-1 ring-border p-4 space-y-3">
      <div className="flex items-center gap-2 flex-wrap">
        {QUICK_EMOJI.map(g => (
          <button
            key={g}
            onClick={() => setEmoji(emoji === g ? undefined : g)}
            className={`w-8 h-8 grid place-items-center rounded-md text-[16px] transition ${
              emoji === g ? 'bg-accent/15 ring-1 ring-accent/30' : 'hover:bg-elevated/60'
            }`}
          >
            {g}
          </button>
        ))}
      </div>

      <div className="flex items-center gap-1.5">
        <span className="text-[10.5px] uppercase tracking-[0.16em] font-semibold text-text-3 mr-2">
          Rating
        </span>
        {Array.from({ length: 10 }).map((_, i) => {
          const n = i + 1
          const on = n <= rating
          return (
            <button
              key={n}
              onClick={() => setRating(rating === n ? 0 : n)}
              aria-label={`Rate ${n} out of 10`}
              className={`w-6 h-6 grid place-items-center rounded transition ${
                on ? 'text-accent' : 'text-text-4 hover:text-text-2'
              }`}
            >
              <Star size={12} fill={on ? 'currentColor' : 'none'} stroke={on ? 0 : 1.5} />
            </button>
          )
        })}
        {rating > 0 && (
          <span className="text-[11px] text-text-3 tabular-nums ml-1">{rating}/10</span>
        )}
      </div>

      <textarea
        value={note}
        onChange={e => setNote(e.target.value)}
        rows={2}
        placeholder="A thought, a quote, or just nothing"
        className="w-full px-3 py-2 rounded-md bg-void/40 ring-1 ring-border focus:ring-accent/50 outline-none text-[12.5px] tracking-tight resize-y leading-relaxed text-text-1 placeholder:text-text-4"
      />

      <div className="flex items-center justify-between gap-2 flex-wrap">
        <label className="inline-flex items-center gap-1.5 text-[11.5px] text-text-2 cursor-pointer">
          <input
            type="checkbox"
            checked={rewatch}
            onChange={e => setRewatch(e.target.checked)}
            className="accent-amber-500"
          />
          Logged as a rewatch
        </label>
        <div className="flex items-center gap-2">
          <button
            onClick={onCancel}
            className="h-8 px-3 rounded-full text-[11.5px] text-text-2 hover:text-text-1 hover:bg-elevated transition focus-ring"
          >
            Cancel
          </button>
          <button
            onClick={() => onSave({ rating: rating || undefined, note: note.trim() || undefined, emoji, rewatch })}
            className="h-8 px-4 rounded-full bg-accent text-void text-[11.5px] font-semibold tracking-tight hover:bg-accent-hover transition focus-ring"
          >
            Log
          </button>
        </div>
      </div>
    </div>
  )
}

function DiaryRow({ entry, onRemove }: { entry: DiaryEntry; onRemove: () => void }) {
  const [confirmingDelete, setConfirmingDelete] = useState(false)
  const date = new Date(entry.watchedAt)
  const dateLabel = date.toLocaleDateString(undefined, {
    year: 'numeric', month: 'short', day: 'numeric',
  })
  return (
    <li className="rounded-lg bg-elevated/40 ring-1 ring-border p-3 group">
      <div className="flex items-start gap-3">
        {entry.emoji && (
          <span className="text-[20px] leading-none mt-0.5 select-none">{entry.emoji}</span>
        )}
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2 flex-wrap text-[11.5px] text-text-3 mb-1 tracking-tight">
            <span className="text-text-2 font-medium tabular-nums">{dateLabel}</span>
            {entry.rating != null && entry.rating > 0 && (
              <>
                <span className="text-text-5">·</span>
                <span className="inline-flex items-center gap-1 text-accent tabular-nums">
                  <Star size={10} fill="currentColor" stroke={0} />
                  {entry.rating}/10
                </span>
              </>
            )}
            {entry.rewatch && (
              <>
                <span className="text-text-5">·</span>
                <span className="text-text-4">rewatch</span>
              </>
            )}
          </div>
          {entry.note && (
            <p className="text-[12.5px] text-text-1 leading-relaxed whitespace-pre-wrap">
              {entry.note}
            </p>
          )}
        </div>
        <button
          onClick={() => {
            if (confirmingDelete) onRemove()
            else setConfirmingDelete(true)
          }}
          onBlur={() => setConfirmingDelete(false)}
          aria-label={confirmingDelete ? 'Confirm delete' : 'Delete entry'}
          className={`w-7 h-7 grid place-items-center rounded transition focus-ring ${
            confirmingDelete
              ? 'text-red-300 bg-red-500/15'
              : 'text-text-4 hover:text-red-300 opacity-0 group-hover:opacity-100'
          }`}
        >
          {confirmingDelete ? <X size={12} stroke={2.5} /> : <Trash2 size={12} stroke={2} />}
        </button>
      </div>
    </li>
  )
}
