import GameGrid from '@/Components/game/GameGrid';
import GameHero, { formatDate } from '@/Components/game/GameHero';
import RatingDistribution from '@/Components/game/RatingDistribution';
import ReviewCard from '@/Components/game/ReviewCard';
import ReviewForm from '@/Components/game/ReviewForm';
import ScreenshotGallery from '@/Components/game/ScreenshotGallery';
import StarRating from '@/Components/game/StarRating';
import StatusPicker, { Status } from '@/Components/game/StatusPicker';
import SystemRequirements from '@/Components/game/SystemRequirements';
import TrailerEmbed from '@/Components/game/TrailerEmbed';
import EmptyState from '@/Components/shared/EmptyState';
import Seo from '@/Components/shared/Seo';
import { Badge } from '@/Components/ui/badge';
import PublicLayout from '@/Layouts/PublicLayout';
import { ease } from '@/lib/motion';
import { PageProps } from '@/types';
import { GameCard, GameDetail, Paginated, ReviewItem } from '@/types/models';
import { Link, router, usePage } from '@inertiajs/react';
import { motion } from 'framer-motion';
import { ExternalLink, MessageSquareText } from 'lucide-react';
import { ReactNode } from 'react';

type Mine = { score: number | null; status: Status | null; review: { id: number; title: string | null; body: string; contains_spoilers: boolean } | null } | null;
type Props = { game: GameDetail; histogram: number[]; reviews: Paginated<ReviewItem>; related: { data: GameCard[] }; mine: Mine };

function Reveal({ children, className }: { children: ReactNode; className?: string }) {
    return (
        <motion.section initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true, margin: '-60px' }} transition={{ duration: 0.6, ease }} className={className}>
            {children}
        </motion.section>
    );
}

const Heading = ({ children, id, aside }: { children: ReactNode; id?: string; aside?: ReactNode }) => (
    <div className="mb-4 flex items-baseline justify-between gap-3">
        <h2 id={id} className="text-h2">{children}</h2>
        {aside}
    </div>
);

function Detail({ label, children }: { label: string; children: ReactNode }) {
    return (
        <div className="grid grid-cols-[96px_1fr] gap-3 py-2.5 text-sm">
            <dt className="text-muted-foreground">{label}</dt>
            <dd className="min-w-0">{children}</dd>
        </div>
    );
}

export default function Show({ game, histogram, reviews, related, mine }: Props) {
    const { auth } = usePage<PageProps>().props;
    const authed = !!auth.user;
    const verified = !!auth.user?.email_verified_at;

    const rate = (score: number) => (authed ? router.put(route('games.rating.store', game.slug), { score }, { preserveScroll: true }) : router.visit(route('login')));
    const clear = () => router.delete(route('games.rating.destroy', game.slug), { preserveScroll: true });

    const actions = (
        <>
            <div className="sm:w-[420px]"><StatusPicker slug={game.slug} status={mine?.status ?? null} authed={authed} layout="row" /></div>
            <div className="flex items-center justify-between gap-4 sm:justify-end">
                <div className="text-left sm:text-right">
                    <p className="text-caption">{mine?.score ? 'Your rating' : 'Rate this game'}</p>
                    {mine?.score ? (
                        <p className="text-sm"><span className="font-semibold">{mine.score}/10</span> · <button onClick={clear} className="text-muted-foreground underline-offset-4 hover:text-foreground hover:underline">Clear</button></p>
                    ) : !authed ? (
                        <Link href={route('login')} className="text-xs text-muted-foreground underline underline-offset-4">Log in to rate</Link>
                    ) : null}
                </div>
                <StarRating value={mine?.score ?? null} onChange={rate} />
            </div>
        </>
    );

    return (
        <PublicLayout>
            <Seo title={game.title} />

            <GameHero game={game} actions={actions} />

            <div className="mt-12 grid gap-10 lg:grid-cols-[minmax(0,1fr)_340px]">
                <div className="min-w-0 space-y-14">
                    <Reveal>
                        <Heading>About</Heading>
                        {game.description.length ? (
                            <div className="max-w-prose space-y-4 text-body text-foreground/85">{game.description.map((p, i) => <p key={i}>{p}</p>)}</div>
                        ) : (
                            <p className="text-sm text-muted-foreground">No description yet.</p>
                        )}
                        {game.tags.length > 0 && (
                            <div className="mt-5 flex flex-wrap gap-2">
                                {game.tags.map((t) => <Link key={t.slug} href={route('catalog', { tag: [t.slug] })} className="rounded-full border border-border px-3 py-1 text-xs text-muted-foreground transition hover:border-foreground/30 hover:text-foreground">{t.name}</Link>)}
                            </div>
                        )}
                    </Reveal>

                    {game.trailer_id && (
                        <Reveal>
                            <Heading>Trailer</Heading>
                            <TrailerEmbed id={game.trailer_id} title={game.title} poster={game.hero ?? game.screenshots[0]?.large} />
                        </Reveal>
                    )}

                    {game.screenshots.length > 0 && (
                        <Reveal>
                            <Heading aside={<span className="text-caption">{game.screenshots.length} images</span>}>Screenshots</Heading>
                            <ScreenshotGallery shots={game.screenshots} title={game.title} />
                        </Reveal>
                    )}

                    {game.system_requirements && (
                        <Reveal>
                            <Heading>System requirements</Heading>
                            <SystemRequirements requirements={game.system_requirements} />
                        </Reveal>
                    )}

                    <Reveal>
                        <Heading id="reviews" aside={<span className="text-caption">{reviews.meta.total} {reviews.meta.total === 1 ? 'review' : 'reviews'}</span>}>Reviews</Heading>
                        <div className="space-y-3">
                            {reviews.data.length ? reviews.data.map((r) => <ReviewCard key={r.id} review={r} />) : <EmptyState icon={MessageSquareText} title="No reviews yet" description="Share what you thought. It helps others decide." />}
                        </div>
                        {reviews.meta.last_page > 1 && (
                            <nav className="mt-5 flex items-center justify-center gap-3 text-sm" aria-label="Reviews pagination">
                                {reviews.links.prev ? <Link href={reviews.links.prev} only={['reviews']} preserveScroll preserveState className="rounded-md px-3 py-1.5 hover:bg-accent">Previous</Link> : <span className="px-3 py-1.5 text-muted-foreground/40">Previous</span>}
                                <span className="text-muted-foreground">{reviews.meta.current_page} / {reviews.meta.last_page}</span>
                                {reviews.links.next ? <Link href={reviews.links.next} only={['reviews']} preserveScroll preserveState className="rounded-md px-3 py-1.5 hover:bg-accent">Next</Link> : <span className="px-3 py-1.5 text-muted-foreground/40">Next</span>}
                            </nav>
                        )}

                        <div className="mt-8 rounded-2xl border border-border bg-card/60 p-5 shadow-soft">
                            <h3 className="text-h3 mb-4">{mine?.review ? 'Your review' : 'Write a review'}</h3>
                            {authed ? <ReviewForm key={mine?.review?.id ?? 'new'} slug={game.slug} review={mine?.review ?? null} verified={verified} /> : <p className="text-sm text-muted-foreground"><Link href={route('login')} className="underline underline-offset-4">Log in</Link> to write a review.</p>}
                        </div>
                    </Reveal>
                </div>

                <aside className="space-y-4 lg:sticky lg:top-20 lg:self-start">
                    <Reveal className="rounded-2xl border border-border bg-card/60 p-5 shadow-soft">
                        <h2 className="text-h3 mb-1">Details</h2>
                        <dl className="divide-y divide-border">
                            <Detail label="Developer">{game.developer ?? '—'}</Detail>
                            <Detail label="Publisher">{game.publisher ?? '—'}</Detail>
                            <Detail label="Released">{formatDate(game.release_date)}</Detail>
                            <Detail label="Platforms"><span className="flex flex-wrap gap-1.5">{game.platforms.length ? game.platforms.map((p) => <Badge key={p.slug} variant="outline">{p.name}</Badge>) : '—'}</span></Detail>
                            <Detail label="Genres">{game.genres.map((g) => g.name).join(', ') || '—'}</Detail>
                            <Detail label="Playtime">{game.playtime_main ? `${game.playtime_main}h main${game.playtime_complete ? ` · ${game.playtime_complete}h complete` : ''}` : '—'}</Detail>
                            <Detail label="Compare"><Link href={route('compare', { games: [game.slug] })} className="underline-offset-4 hover:underline">Compare with other games</Link></Detail>
                            {game.website_url && (
                                <Detail label="Website"><a href={game.website_url} target="_blank" rel="noopener noreferrer nofollow" className="inline-flex items-center gap-1 underline-offset-4 hover:underline">Official site <ExternalLink className="size-3" /></a></Detail>
                            )}
                        </dl>
                    </Reveal>
                    <Reveal className="rounded-2xl border border-border bg-card/60 p-5 shadow-soft">
                        <h2 className="text-h3 mb-4">Community ratings</h2>
                        <RatingDistribution histogram={histogram} avg={game.rating_avg} count={game.rating_count} />
                    </Reveal>
                </aside>
            </div>

            {related.data.length > 0 && (
                <Reveal className="mt-20">
                    <Heading>Similar games</Heading>
                    <GameGrid games={related.data} />
                </Reveal>
            )}
        </PublicLayout>
    );
}
