import { useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
import { motion } from 'framer-motion'
import { Star, Clock, Flame, Calendar, ChevronRight } from '../lib/icons'
import { useLibraryItems, useItemsByIds } from '../hooks/use-jellyfin'
import { usePersonalData } from '../stores/personal-data-store'
import { useDiary } from '../stores/diary-store'
import { genreBreakdown, watchStreak, totalHoursWatched, longestBinge } from '../lib/watch-stats'
import { jellyfinClient } from '../api/jellyfin'

const CURRENT_YEAR = new Date().getFullYear()

/**
 * Personal profile page - the home for the user's own data layer:
 *  - Watch streak (#46)
 *  - Genre breakdown (#44)
 *  - Year-in-Review summary (#43)
 *  - Recent diary entries (#47, surfaced)
 */
export default function ProfilePage() {
  const navigate = useNavigate()
  const auth = jellyfinClient.getAuthState()
  const { data } = useLibraryItems(undefined, {
    includeItemTypes: ['Movie', 'Series', 'Episode'],
    sortBy: ['DatePlayed'],
    sortOrder: ['Descending'],
    filters: ['IsPlayed'],
    limit: 1000,
  })
  const items = useMemo(() => data?.Items || [], [data?.Items])

  const yearItems = useMemo(
    () =>
      items.filter(it => {
        const raw = it.UserData?.LastPlayedDate
        if (!raw) return false
        return new Date(raw).getFullYear() === CURRENT_YEAR
      }),
    [items],
  )

  const streak = useMemo(() => watchStreak(items), [items])
  const breakdown = useMemo(() => genreBreakdown(items).slice(0, 8), [items])
  const breakdownYear = useMemo(() => genreBreakdown(yearItems).slice(0, 6), [yearItems])
  const hoursAll = useMemo(() => totalHoursWatched(items), [items])
  const hoursYear = useMemo(() => totalHoursWatched(yearItems), [yearItems])
  const binge = useMemo(() => longestBinge(yearItems), [yearItems])

  const personal = usePersonalData(s => s.entries)
  // Top rated by personal rating - independent of played status, so an
  // item rated highly that the user hasn't gotten around to opening
  // still shows up. Resolve metadata via a separate `useItemsByIds`
  // call rather than joining against the played-items list.
  const topRatedIds = useMemo(
    () =>
      Object.entries(personal)
        .filter(([, e]) => e.rating >= 8)
        .sort((a, b) => b[1].rating - a[1].rating)
        .slice(0, 10)
        .map(([id]) => id),
    [personal],
  )
  const { data: topRatedItems = [] } = useItemsByIds(topRatedIds)
  const topRatedPersonal = useMemo(() => {
    return topRatedIds
      .map(id => {
        const item = topRatedItems.find(it => it.Id === id) || items.find(i => i.Id === id)
        const entry = personal[id]
        if (!item || !entry) return null
        return { id, rating: entry.rating, rewatchCount: entry.rewatchCount, item }
      })
      .filter((x): x is { id: string; rating: number; rewatchCount: number; item: any } => !!x)
  }, [topRatedIds, topRatedItems, personal, items])

  const diary = useDiary(s => s.entries)
  const recentDiary = useMemo(
    () =>
      [...diary]
        .sort((a, b) => b.watchedAt.localeCompare(a.watchedAt))
        .slice(0, 8),
    [diary],
  )

  return (
    <div className="px-7 pb-12 pt-6">
      <header className="mb-8 flex items-end justify-between gap-6 flex-wrap">
        <div>
          <p className="text-[11px] uppercase tracking-[0.18em] font-semibold text-text-3 mb-1.5">
            Profile
          </p>
          <h1 className="font-display text-3xl font-bold tracking-tight text-text-1 leading-tight">
            {auth?.userName ? `${auth.userName}'s year` : 'Your year'}
          </h1>
          <p className="text-[13px] text-text-3 mt-1.5">
            Stats and notes that live only on this device.
          </p>
        </div>
        <button
          onClick={() => navigate('/stats')}
          className="inline-flex items-center gap-1.5 h-9 px-3.5 rounded-md text-[12.5px] font-medium bg-elevated/60 text-text-2 border border-border hover:border-border-hover hover:text-text-1 transition-all duration-150 focus-ring"
        >
          See full stats
          <ChevronRight size={13} stroke={2} />
        </button>
      </header>

      {/* Stat tiles */}
      <div className="grid grid-cols-2 md:grid-cols-4 xl:grid-cols-6 gap-3 mb-10">
        <StatTile
          label="Current streak"
          value={String(streak.current)}
          unit={streak.current === 1 ? 'day' : 'days'}
          accent={streak.current >= 3}
          icon={<Flame size={14} className="text-accent" />}
          hint={streak.longest > streak.current ? `Best: ${streak.longest}` : 'Keep going'}
        />
        <StatTile
          label={`Watched in ${CURRENT_YEAR}`}
          value={String(yearItems.length)}
          unit={yearItems.length === 1 ? 'item' : 'items'}
          icon={<Calendar size={14} className="text-accent" />}
        />
        <StatTile
          label="Hours this year"
          value={hoursYear.toFixed(0)}
          unit="hours"
          icon={<Clock size={14} className="text-accent" />}
          hint={`${hoursAll.toFixed(0)} all-time`}
        />
        <StatTile
          label="Longest binge"
          value={String(binge.count)}
          unit={binge.count === 1 ? 'item' : 'items'}
          icon={<Flame size={14} className="text-accent" />}
          hint={binge.day || 'No binge yet'}
        />
      </div>

      {/* Genre breakdown */}
      <section className="mb-10">
        <h2 className="text-[14px] font-semibold text-text-1 mb-3 tracking-tight">
          Genre breakdown
        </h2>
        {breakdown.length === 0 ? (
          <p className="text-[12.5px] text-text-3">No genre data yet.</p>
        ) : (
          <div className="space-y-2">
            {breakdown.map((g, i) => (
              <GenreBar key={g.genre} share={g} index={i} />
            ))}
          </div>
        )}
        {breakdownYear.length > 0 && (
          <p className="mt-4 text-[12px] text-text-3 leading-relaxed">
            Top this year:{' '}
            {breakdownYear.map((g, i) => (
              <span key={g.genre}>
                <span className="text-text-2 font-medium">{g.genre}</span>
                <span className="text-text-4 tabular-nums"> {(g.share * 100).toFixed(0)}%</span>
                {i < breakdownYear.length - 1 && <span className="text-text-5"> · </span>}
              </span>
            ))}
          </p>
        )}
      </section>

      {/* Year in Review - top personal ratings */}
      <section className="mb-10">
        <h2 className="text-[14px] font-semibold text-text-1 mb-3 tracking-tight">
          Your top picks
        </h2>
        {topRatedPersonal.length === 0 ? (
          <p className="text-[12.5px] text-text-3">
            No 8+/10 personal ratings yet. Use the rating row on a detail page to mark your favourites.
          </p>
        ) : (
          <ol className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-2">
            {topRatedPersonal.map((entry, i) => (
              <TopPickRow key={entry.id} index={i + 1} entry={entry} />
            ))}
          </ol>
        )}
      </section>

      {/* Recent diary */}
      {recentDiary.length > 0 && (
        <section className="mb-10">
          <h2 className="text-[14px] font-semibold text-text-1 mb-3 tracking-tight">
            Recent diary
          </h2>
          <ul className="space-y-2">
            {recentDiary.map(d => (
              <li
                key={d.id}
                className="rounded-lg bg-elevated/40 ring-1 ring-border p-3 flex items-start gap-3"
              >
                {d.emoji && <span className="text-[20px] leading-none">{d.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">
                      {new Date(d.watchedAt).toLocaleDateString(undefined, {
                        year: 'numeric', month: 'short', day: 'numeric',
                      })}
                    </span>
                    <span className="text-text-5">·</span>
                    <NavLink itemId={d.itemId} name={d.itemName} />
                    {d.rating != null && d.rating > 0 && (
                      <>
                        <span className="text-text-5">·</span>
                        <span className="inline-flex items-center gap-0.5 text-accent tabular-nums">
                          <Star size={10} fill="currentColor" stroke={0} />
                          {d.rating}/10
                        </span>
                      </>
                    )}
                  </div>
                  {d.note && (
                    <p className="text-[12.5px] text-text-1 leading-relaxed line-clamp-3">
                      {d.note}
                    </p>
                  )}
                </div>
              </li>
            ))}
          </ul>
        </section>
      )}
    </div>
  )
}

function StatTile({
  label,
  value,
  unit,
  hint,
  icon,
  accent,
}: {
  label: string
  value: string
  unit?: string
  hint?: string
  icon?: React.ReactNode
  accent?: boolean
}) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 6 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
      className={`rounded-xl p-4 ring-1 ${
        accent ? 'bg-accent/10 ring-accent/30' : 'bg-elevated/40 ring-border'
      }`}
    >
      <div className="flex items-center gap-2 text-[10.5px] uppercase tracking-[0.16em] font-semibold text-text-3 mb-2">
        {icon}
        {label}
      </div>
      <div className="flex items-baseline gap-1.5">
        <span className="font-display text-[28px] font-bold text-text-1 tabular-nums leading-none">
          {value}
        </span>
        {unit && <span className="text-[12px] text-text-3 tracking-tight">{unit}</span>}
      </div>
      {hint && <p className="text-[11px] text-text-4 mt-1.5 tracking-tight">{hint}</p>}
    </motion.div>
  )
}

function GenreBar({ share, index }: { share: { genre: string; count: number; share: number }; index: number }) {
  const pct = Math.max(2, Math.round(share.share * 100))
  return (
    <motion.div
      initial={{ opacity: 0, x: -6 }}
      animate={{ opacity: 1, x: 0 }}
      transition={{ duration: 0.3, delay: Math.min(index * 0.04, 0.4) }}
      className="flex items-center gap-3 text-[12px]"
    >
      <span className="w-32 shrink-0 text-text-2 font-medium tracking-tight truncate">
        {share.genre}
      </span>
      <div className="flex-1 h-2.5 rounded-full bg-elevated/60 overflow-hidden">
        <motion.div
          initial={{ width: 0 }}
          animate={{ width: `${pct}%` }}
          transition={{ duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
          className="h-full bg-accent"
        />
      </div>
      <span className="w-16 shrink-0 text-right text-text-3 tabular-nums">
        {(share.share * 100).toFixed(0)}%
      </span>
    </motion.div>
  )
}

function TopPickRow({
  index,
  entry,
}: {
  index: number
  entry: { id: string; rating: number; rewatchCount: number; item: any }
}) {
  const navigate = useNavigate()
  return (
    <li>
      <button
        onClick={() => navigate(`/item/${entry.id}`)}
        className="w-full flex items-center gap-3 p-2.5 rounded-lg bg-elevated/40 ring-1 ring-border hover:ring-border-strong hover:bg-elevated/70 transition text-left focus-ring"
      >
        <span className="w-7 h-7 grid place-items-center rounded-full bg-accent/15 text-accent text-[11px] font-bold tabular-nums shrink-0">
          {index}
        </span>
        <div className="min-w-0 flex-1">
          <p className="text-[13px] text-text-1 font-medium truncate tracking-tight">
            {entry.item.Name}
          </p>
          <p className="text-[11px] text-text-3 truncate tabular-nums">
            {entry.item.ProductionYear}
            {entry.rewatchCount > 0 && ` · ${entry.rewatchCount} rewatch${entry.rewatchCount === 1 ? '' : 'es'}`}
          </p>
        </div>
        <span className="inline-flex items-center gap-1 text-accent tabular-nums shrink-0">
          <Star size={11} fill="currentColor" stroke={0} />
          {entry.rating}/10
        </span>
      </button>
    </li>
  )
}

function NavLink({ itemId, name }: { itemId: string; name: string }) {
  const navigate = useNavigate()
  return (
    <button
      onClick={() => navigate(`/item/${itemId}`)}
      className="text-text-2 hover:text-accent transition focus-ring rounded font-medium truncate max-w-[14rem]"
    >
      {name}
    </button>
  )
}
