import { useMemo } from 'react'
import { Star } from '../../lib/icons'
import type { RTRating } from '../../api/rotten-tomatoes'
import { getPersonalEntry } from '../../stores/personal-data-store'
import { usePersonalData } from '../../stores/personal-data-store'
import { useWikiSection } from '../../hooks/use-external'

interface Props {
  /** Jellyfin item id - drives the personal rating lookup. Pass null for
   *  TMDB-only contexts where personal data doesn't apply. */
  itemId?: string | null
  rt?: RTRating | null
  imdbRating?: number | null
  /** TMDB community score on a 0-10 scale. */
  tmdbScore?: number | null
  tmdbVotes?: number | null
  /** Jellyfin's own averaged community rating (item.CommunityRating). */
  jellyfinCommunityRating?: number | null
  /** Wikipedia article title to fetch the Critical-response / Reception
   *  section from. If null, the prose summary block is hidden. */
  wikiTitle?: string | null
}

interface Rating {
  source: string
  /** 0-100 normalised score for the aggregate calc. */
  norm: number
  /** Display value as the user expects it. */
  display: string
  badge: React.ReactNode
  href?: string
}

/**
 * Single home for everything users mean when they ask "is it any good?"
 * Aggregates RT critics, RT audience, IMDb, TMDB, Jellyfin community,
 * and the user's own rating into one panel, computes a meta-average,
 * and pairs it with the Wikipedia critical-response paragraph when
 * available so the page actually says *why* the score is what it is.
 */
export default function ReceptionPanel({
  itemId,
  rt,
  imdbRating,
  tmdbScore,
  tmdbVotes,
  jellyfinCommunityRating,
  wikiTitle,
}: Props) {
  // Subscribe so personal rating changes re-render the aggregate live.
  usePersonalData(s => s.entries)
  const personal = itemId ? getPersonalEntry(itemId) : null
  const personalRating = personal && personal.rating > 0 ? personal.rating : null

  // Wikipedia "Critical response" section (with "Reception" fallback
  // tried inside the same hook - many articles use either heading).
  const wikiCritical = useWikiSection(wikiTitle ?? null, 'Critical response')
  const wikiReception = useWikiSection(
    // Avoid the second fetch when the first hit returns content.
    wikiTitle && !wikiCritical.data ? wikiTitle : null,
    'Reception',
  )
  const wikiText = wikiCritical.data?.extract || wikiReception.data?.extract || null

  const ratings = useMemo<Rating[]>(() => {
    const out: Rating[] = []
    if (rt?.criticsScore != null) {
      out.push({
        source: 'Tomatometer',
        norm: rt.criticsScore,
        display: `${Math.round(rt.criticsScore)}%`,
        href: rt.url,
        badge: (
          <span className="text-[14px] leading-none">
            {rt.criticsRating === 'Rotten' ? '🤢' : '🍅'}
          </span>
        ),
      })
    }
    if (rt?.audienceScore != null) {
      out.push({
        source: 'Audience',
        norm: rt.audienceScore,
        display: `${Math.round(rt.audienceScore)}%`,
        href: rt.url,
        badge: <span className="text-[14px] leading-none">🍿</span>,
      })
    }
    if (typeof imdbRating === 'number' && imdbRating > 0) {
      out.push({
        source: 'IMDb',
        norm: imdbRating * 10,
        display: imdbRating.toFixed(1),
        badge: (
          <span className="inline-flex items-center justify-center px-1 h-3.5 rounded-[2px] bg-[#f5c518] text-[8.5px] font-bold text-black tracking-tight">
            IMDb
          </span>
        ),
      })
    }
    if (typeof tmdbScore === 'number' && tmdbScore > 0) {
      out.push({
        source: tmdbVotes ? `TMDB - ${tmdbVotes.toLocaleString()} votes` : 'TMDB',
        norm: tmdbScore * 10,
        display: `${Math.round(tmdbScore * 10)}%`,
        badge: <Star size={13} className="text-accent" fill="currentColor" stroke={0} />,
      })
    }
    if (typeof jellyfinCommunityRating === 'number' && jellyfinCommunityRating > 0) {
      out.push({
        source: 'Jellyfin community',
        norm: jellyfinCommunityRating * 10,
        display: jellyfinCommunityRating.toFixed(1),
        badge: <Star size={13} className="text-cool" fill="currentColor" stroke={0} />,
      })
    }
    if (personalRating != null) {
      out.push({
        source: 'Your rating',
        norm: personalRating * 10,
        display: `${personalRating}/10`,
        badge: <Star size={13} className="text-accent" fill="currentColor" stroke={0} />,
      })
    }
    return out
  }, [rt, imdbRating, tmdbScore, tmdbVotes, jellyfinCommunityRating, personalRating])

  const aggregate = useMemo(() => {
    if (ratings.length === 0) return null
    const sum = ratings.reduce((acc, r) => acc + r.norm, 0)
    return Math.round(sum / ratings.length)
  }, [ratings])

  if (ratings.length === 0 && !wikiText) return null

  // Trim the wiki prose to the first 2 paragraphs so the panel stays calm.
  const wikiParagraphs = wikiText
    ? wikiText.split(/\n{2,}/).map(s => s.trim()).filter(p => p.length > 40).slice(0, 2)
    : []

  return (
    <div className="rounded-2xl bg-elevated/30 ring-1 ring-border overflow-hidden">
      {aggregate != null && (
        <div className="px-5 py-4 flex items-center gap-5 border-b border-border/60 bg-void/30">
          <div className="shrink-0 relative">
            <AggregateGauge value={aggregate} />
          </div>
          <div className="min-w-0">
            <p className="text-[10.5px] uppercase tracking-[0.18em] font-semibold text-text-3 mb-1">
              Aggregate
            </p>
            <p className="text-[12.5px] text-text-2 leading-snug">
              Average across {ratings.length} {ratings.length === 1 ? 'source' : 'sources'}.
              {ratings.length > 1 && (
                <span className="text-text-4"> Equally weighted - the simplest honest math.</span>
              )}
            </p>
          </div>
        </div>
      )}

      {ratings.length > 0 && (
        <div className="px-5 py-4 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-3 gap-3">
          {ratings.map(r => (
            <RatingCell key={r.source} rating={r} />
          ))}
        </div>
      )}

      {wikiParagraphs.length > 0 && (
        <div className="border-t border-border/60 px-5 py-4 bg-void/15">
          <p className="text-[10.5px] uppercase tracking-[0.18em] font-semibold text-text-3 mb-3">
            Critical response
          </p>
          <div className="space-y-3 text-[13px] text-text-2 leading-relaxed">
            {wikiParagraphs.map((p, i) => (
              <p key={i}>{p}</p>
            ))}
          </div>
          <p className="mt-3 text-[10.5px] text-text-5 tracking-tight">
            Source: Wikipedia, "{(wikiCritical.data || wikiReception.data)?.title}"
          </p>
        </div>
      )}
    </div>
  )
}

function RatingCell({ rating }: { rating: Rating }) {
  const content = (
    <div className="flex items-center gap-2.5 p-2.5 rounded-lg bg-void/30 ring-1 ring-border/70 hover:ring-border-strong transition-colors h-full">
      <span className="shrink-0 w-7 h-7 grid place-items-center">{rating.badge}</span>
      <div className="min-w-0 flex-1">
        <p className="text-[10.5px] uppercase tracking-[0.14em] font-semibold text-text-3 truncate">
          {rating.source}
        </p>
        <p className="text-[15px] font-display font-bold text-text-1 tabular-nums leading-none mt-0.5">
          {rating.display}
        </p>
      </div>
    </div>
  )
  if (rating.href) {
    return (
      <a href={rating.href} target="_blank" rel="noopener noreferrer" className="block focus-ring rounded-lg">
        {content}
      </a>
    )
  }
  return content
}

/**
 * Donut-style score gauge. Sweeps a ring proportional to the score and
 * tints the stroke amber→cool depending on how high it is. Pure SVG, no
 * external dependency.
 */
function AggregateGauge({ value }: { value: number }) {
  const clamped = Math.max(0, Math.min(100, value))
  const radius = 28
  const circumference = 2 * Math.PI * radius
  const dash = (clamped / 100) * circumference
  const tone =
    clamped >= 80 ? 'var(--color-accent)'
    : clamped >= 60 ? 'var(--color-accent-deep)'
    : clamped >= 40 ? 'var(--color-warning)'
    : 'var(--color-error)'
  return (
    <svg viewBox="0 0 72 72" width={64} height={64} className="-rotate-90">
      <circle cx={36} cy={36} r={radius} fill="none" stroke="var(--color-border)" strokeWidth={6} />
      <circle
        cx={36}
        cy={36}
        r={radius}
        fill="none"
        stroke={tone}
        strokeWidth={6}
        strokeLinecap="round"
        strokeDasharray={`${dash} ${circumference}`}
        style={{ transition: 'stroke-dasharray 0.6s cubic-bezier(0.16, 1, 0.3, 1)' }}
      />
      <text
        x="36"
        y="40"
        textAnchor="middle"
        className="font-display font-bold fill-text-1"
        style={{ fontSize: 18, transform: 'rotate(90deg)', transformOrigin: '36px 36px' }}
      >
        {clamped}
      </text>
    </svg>
  )
}
