import { useMemo } from 'react'
import { motion } from 'framer-motion'
import { Star, RefreshCw, CalendarStar } from '../../lib/icons'
import { useDiary } from '../../stores/diary-store'

interface Props {
  itemId?: string | null
}

/**
 * Letterboxd-style watch timeline. Reads every diary entry for the
 * current item from the diary store, sorts oldest-first so the timeline
 * reads chronologically left-to-right, and renders each as a card with
 * date / rating / note / rewatch indicator.
 *
 * Hides itself when there's no diary history - cold-start users
 * shouldn't see an empty section staring back at them.
 */
export default function WatchTimeline({ itemId }: Props) {
  const entries = useDiary(s => s.entries)
  const ordered = useMemo(() => {
    if (!itemId) return []
    return entries
      .filter(e => e.itemId === itemId)
      .sort((a, b) => a.watchedAt.localeCompare(b.watchedAt))
  }, [entries, itemId])

  if (ordered.length === 0) return null

  const rewatches = ordered.filter(e => e.rewatch).length
  const firstDate = ordered[0].watchedAt
  const lastDate = ordered[ordered.length - 1].watchedAt
  const spanLabel = ordered.length === 1
    ? `Watched once - ${formatLong(firstDate)}`
    : rewatches > 0
      ? `${ordered.length} watches over ${spanText(firstDate, lastDate)} - ${rewatches} ${rewatches === 1 ? 'rewatch' : 'rewatches'}`
      : `${ordered.length} watches over ${spanText(firstDate, lastDate)}`

  return (
    <div className="space-y-3">
      <div className="flex items-center gap-2.5">
        <span className="w-7 h-7 grid place-items-center rounded-full bg-accent/15 ring-1 ring-accent/30">
          <CalendarStar size={13} className="text-accent" />
        </span>
        <p className="text-[12.5px] text-text-2 tracking-tight">{spanLabel}</p>
      </div>

      <div className="relative -mx-1 overflow-x-auto hide-scrollbar">
        <ol className="flex items-stretch gap-2 px-1 min-w-max">
          {ordered.map((entry, i) => (
            <motion.li
              key={entry.id}
              initial={{ opacity: 0, y: 6 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.3, delay: Math.min(i * 0.04, 0.4) }}
              className="relative w-[200px] shrink-0 rounded-xl bg-elevated/30 ring-1 ring-border hover:ring-border-strong transition-colors p-3"
            >
              <div className="flex items-center gap-2 mb-1.5">
                <span className="text-[10.5px] uppercase tracking-[0.14em] font-semibold text-text-3 tabular-nums">
                  {formatShort(entry.watchedAt)}
                </span>
                {entry.rewatch && (
                  <span
                    title="Rewatch"
                    className="inline-flex items-center gap-0.5 h-4 px-1 rounded-full bg-cool/15 text-cool text-[9.5px] font-semibold uppercase tracking-[0.1em]"
                  >
                    <RefreshCw size={9} stroke={2.4} />
                    Rewatch
                  </span>
                )}
              </div>
              <div className="flex items-center gap-1.5 mb-1.5">
                {entry.emoji && <span className="text-[18px] leading-none">{entry.emoji}</span>}
                {typeof entry.rating === 'number' && entry.rating > 0 && (
                  <span className="inline-flex items-center gap-0.5 text-accent tabular-nums text-[13px] font-display font-bold">
                    <Star size={12} fill="currentColor" stroke={0} />
                    {entry.rating}
                    <span className="text-text-4 text-[10.5px] font-normal font-sans ml-0.5">/10</span>
                  </span>
                )}
              </div>
              {entry.note ? (
                <p className="text-[11.5px] text-text-2 leading-snug line-clamp-3">
                  {entry.note}
                </p>
              ) : (
                <p className="text-[11px] text-text-5 italic">No note</p>
              )}
              {i < ordered.length - 1 && (
                <span
                  aria-hidden
                  className="absolute top-1/2 -right-2 w-2 h-px bg-border"
                />
              )}
            </motion.li>
          ))}
        </ol>
      </div>
    </div>
  )
}

function formatShort(iso: string): string {
  const d = new Date(iso)
  if (Number.isNaN(d.getTime())) return ''
  return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })
}

function formatLong(iso: string): string {
  const d = new Date(iso)
  if (Number.isNaN(d.getTime())) return ''
  return d.toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' })
}

function spanText(firstIso: string, lastIso: string): string {
  const a = new Date(firstIso).getTime()
  const b = new Date(lastIso).getTime()
  const days = Math.max(0, Math.round((b - a) / 86_400_000))
  if (days === 0) return 'a single day'
  if (days < 7) return `${days} ${days === 1 ? 'day' : 'days'}`
  if (days < 60) {
    const weeks = Math.round(days / 7)
    return `${weeks} ${weeks === 1 ? 'week' : 'weeks'}`
  }
  if (days < 365) {
    const months = Math.round(days / 30)
    return `${months} ${months === 1 ? 'month' : 'months'}`
  }
  const years = (days / 365).toFixed(1).replace(/\.0$/, '')
  return `${years} ${years === '1' ? 'year' : 'years'}`
}
