import { useState } from 'react'
import { Tag } from '../../lib/icons'
import { Section } from '../ui/SectionLabel'
import type { BaseItemDto } from '../../api/types'
import type {
  TmdbMovie,
  TmdbTvShow,
  TmdbCollection,
  TmdbWatchProviders,
  TmdbKeyword,
  TmdbReview,
  TmdbVideo,
  TmdbCastMember,
} from '../../api/tmdb'
import type { CinemetaMeta } from '../../api/cinemeta'
import type { TvmazeShow } from '../../api/tvmaze'
import type { WikidataAward, WikidataLocation } from '../../api/wikidata'
import type { RTRating } from '../../api/rotten-tomatoes'

type WikiSection = { extract: string; title: string }
import { usePreferencesStore } from '../../stores/preferences-store'
import { useDiary } from '../../stores/diary-store'
import { parseImdbRating } from '../../lib/episode-meta'
import { hasTechSpecs } from './TechSpecs'
import VersionsSelector from './VersionsSelector'
import ReadingMode from './ReadingMode'
import SeriesSection from './SeriesSection'
import EpisodeExtras from './EpisodeExtras'
import CastList from './CastList'
import CrewGrid from './CrewGrid'
import ComposerBlock from './ComposerBlock'
import FactsPanel from './FactsPanel'
import WhereToWatch from './WhereToWatch'
import SeriesStatusBlock from './SeriesStatusBlock'
import VideosSection from './VideosSection'
import ProductionTrivia from './ProductionTrivia'
import ReceptionPanel from './ReceptionPanel'
import WatchTimeline from './WatchTimeline'
import FilmingLocationsMap from './FilmingLocationsMap'
import AwardsBlock from './AwardsBlock'
import TechSpecs from './TechSpecs'
import PersonalSection from './PersonalSection'
import DiarySection from './DiarySection'
import CollectionStrip from './CollectionStrip'
import ReviewsSection from './ReviewsSection'
import DiscoveryRows from './DiscoveryRows'
import FromSameRow from './FromSameRow'
import { getSeriesAirInfo } from '../../lib/item-types'

interface Props {
  item: BaseItemDto
  itemId: string | undefined
  itemType: string
  imdbId: string | null
  tmdbId: string | null | undefined
  tmdbMovieData: TmdbMovie | null | undefined
  tmdbTvData: TmdbTvShow | null | undefined
  tmdbCollectionData: TmdbCollection | null | undefined
  cinemetaData: CinemetaMeta | null | undefined
  tvmazeData: TvmazeShow | null | undefined
  wikiProduction: WikiSection | null | undefined
  awardsData: WikidataAward[] | null | undefined
  locationsData: WikidataLocation[] | null | undefined
  rtData: RTRating | null | undefined
  /** Wikipedia article title for the item - the ReceptionPanel uses
   *  this to pull the Critical-response section. */
  wikiTitle: string | null
  region: string
  watchProviders: TmdbWatchProviders | null | undefined
  cast: TmdbCastMember[]
  crew: TmdbCastMember[]
  keywords: TmdbKeyword[]
  reviews: TmdbReview[]
  videos: TmdbVideo[] | undefined
  recommendations: { id: number; adult?: boolean }[]
  similar: { id: number; adult?: boolean }[]
  libraryMap: Map<string, { id: string; name: string; type: string }> | undefined
  overview: string
  overviewSource: string | null
  sources: { Id?: string | null }[]
  activeSourceId: string | null
  onSourceChange: (id: string | null) => void
}

export default function DetailMainSections({
  item,
  itemId,
  itemType,
  imdbId,
  tmdbId,
  tmdbMovieData,
  tmdbTvData,
  tmdbCollectionData,
  cinemetaData,
  tvmazeData,
  wikiProduction,
  awardsData,
  locationsData,
  rtData,
  wikiTitle,
  region,
  watchProviders,
  cast,
  crew,
  keywords,
  reviews,
  videos,
  recommendations,
  similar,
  libraryMap,
  overview,
  overviewSource,
  sources,
  activeSourceId,
  onSourceChange,
}: Props) {
  const prefs = usePreferencesStore()
  const hasDiaryEntries = useDiary(s => itemId ? s.entries.some(e => e.itemId === itemId) : false)
  const [readingModeOpen, setReadingModeOpen] = useState(false)

  return (
    <>
      <div className="relative px-7 pt-2 space-y-10">
        {/* Versions selector when there's more than one source */}
        {sources.length > 1 && (
          <Section label="Versions">
            <VersionsSelector
              item={item}
              selectedSourceId={activeSourceId}
              onChange={onSourceChange}
            />
          </Section>
        )}

        {/* Synopsis */}
        {overview && (
          <Section label="Overview" id="detail-overview">
            <p className="text-[15px] text-text-2 leading-[1.7] max-w-[68ch] tracking-[-0.005em] [text-wrap:pretty]">
              {overview}
            </p>
            <div className="mt-2 flex items-center gap-3 flex-wrap">
              {overviewSource && (
                <p className="text-[10.5px] text-text-4">Source: {overviewSource}</p>
              )}
              {overview.length > 600 && (
                <button
                  onClick={() => setReadingModeOpen(true)}
                  className="text-[11.5px] text-accent hover:text-accent-hover transition tracking-tight focus-ring rounded"
                >
                  Open in reader
                </button>
              )}
            </div>
          </Section>
        )}
        <ReadingMode
          open={readingModeOpen}
          onClose={() => setReadingModeOpen(false)}
          title={item.Name || ''}
          body={overview}
          source={overviewSource}
        />

        {/* Watch timeline: the user's personal history with this title.
            Letterboxd-flavoured chronology of diary entries. Self-hides
            when there's no diary history. */}
        {hasDiaryEntries && itemId && (
          <Section label="Your watches">
            <WatchTimeline itemId={itemId} />
          </Section>
        )}

        {/* Reception: aggregate of every available rating + critical
            response prose. Replaces the ratings strip that used to live
            inside the About / FactsPanel section. */}
        {(itemType === 'Movie' || itemType === 'Series') && (
          <Section label="Reception" id="detail-reception">
            <ReceptionPanel
              itemId={itemId}
              rt={rtData}
              imdbRating={parseImdbRating(cinemetaData?.imdbRating)}
              tmdbScore={(itemType === 'Movie' ? tmdbMovieData?.vote_average : tmdbTvData?.vote_average) ?? null}
              tmdbVotes={(itemType === 'Movie' ? tmdbMovieData?.vote_count : tmdbTvData?.vote_count) ?? null}
              jellyfinCommunityRating={item.CommunityRating ?? null}
              wikiTitle={wikiTitle}
            />
          </Section>
        )}

        {/* Series episodes - lead with what the user came for on a series
            page. Full-width because the table scrolls and packs many rows. */}
        {itemType === 'Series' && itemId && (
          <div id="detail-episodes" className="scroll-mt-4">
            <SeriesSection seriesId={itemId} imdbId={imdbId} tmdbId={tmdbId ? Number(tmdbId) : null} />
          </div>
        )}

        {/* Episode-specific extras (only on Episode pages) */}
        {itemType === 'Episode' && prefs.detail.show.episodeExtras && (
          <Section label="">
            <EpisodeExtras item={item} />
          </Section>
        )}

        {/* People row: Cast + Crew side-by-side */}
        {(cast.length > 0 || crew.length > 0) && (
          <div className="grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-10">
            {cast.length > 0 && (
              <Section label="Cast" id="detail-cast">
                <CastList cast={cast} fallbackPeople={item.People} />
              </Section>
            )}
            {crew.length > 0 && (
              <Section label="Crew">
                <CrewGrid crew={crew} />
                <div className="mt-3">
                  <ComposerBlock crew={crew} />
                </div>
              </Section>
            )}
          </div>
        )}

        {/* "What is this" cluster: About + Where to Watch + Series Status
            flow into a CSS multi-column layout. Items are packed by content
            height (newspaper-style) so a tall About doesn't leave a 600px
            void next to a short Where to Watch row. */}
        {((itemType === 'Movie' || itemType === 'Series') || watchProviders) && (
          <div className="columns-1 lg:columns-2 gap-8 [column-fill:balance]">
            {(itemType === 'Movie' || itemType === 'Series') && (
              <div className="break-inside-avoid mb-8">
                <Section label="About">
                  <FactsPanel
                    itemType={itemType}
                    movie={tmdbMovieData || null}
                    tv={tmdbTvData || null}
                    region={region}
                  />
                </Section>
              </div>
            )}
            {watchProviders && (
              <div className="break-inside-avoid mb-8">
                <WhereToWatch providers={watchProviders} defaultRegion={region} />
              </div>
            )}
            {itemType === 'Series' && (
              <div className="break-inside-avoid mb-8">
                <Section label="Series status">
                  <SeriesStatusBlock
                    show={tmdbTvData ?? undefined}
                    tvmazeShow={tvmazeData || null}
                    jellyfinAirDays={getSeriesAirInfo(item).airDays}
                    jellyfinAirTime={getSeriesAirInfo(item).airTime}
                  />
                </Section>
              </div>
            )}
          </div>
        )}

        {/* Videos */}
        {prefs.detail.show.videos && (videos?.length ?? 0) > 0 && (
          <Section label="Videos">
            <VideosSection videos={videos} />
          </Section>
        )}

        {/* Trivia */}
        {prefs.detail.show.trivia && (wikiProduction?.extract || (keywords.length > 0 && wikiProduction)) && (
          <Section label="Trivia" id="detail-trivia">
            <ProductionTrivia
              keywords={keywords}
              wikiProduction={wikiProduction}
            />
          </Section>
        )}

        {/* Filming locations */}
        {prefs.detail.show.filmingLocations && (locationsData?.length ?? 0) > 0 && (
          <Section label="Filming locations">
            <FilmingLocationsMap locations={locationsData} />
          </Section>
        )}

        {/* Activity cluster: Awards + Tech specs + Personal + Diary in a
            multi-column flow so wildly different content heights pack
            efficiently. */}
        {((prefs.detail.show.awards && (awardsData?.length ?? 0) > 0)
          || hasTechSpecs(item)
          || keywords.length > 0
          || (item.Id && !String(item.Id).startsWith('tmdb-') && (item.Type === 'Movie' || item.Type === 'Series'))) && (
          <div className="columns-1 lg:columns-2 gap-8 [column-fill:balance]">
            {prefs.detail.show.awards && (awardsData?.length ?? 0) > 0 && (
              <div className="break-inside-avoid mb-8">
                <Section label="Awards">
                  <AwardsBlock awards={awardsData} />
                </Section>
              </div>
            )}
            {hasTechSpecs(item) && (
              <div className="break-inside-avoid mb-8">
                <Section label="Tech specs">
                  <TechSpecs item={item} />
                </Section>
              </div>
            )}
            {item.Id && !String(item.Id).startsWith('tmdb-') && (item.Type === 'Movie' || item.Type === 'Series') && prefs.detail.show.personal && (
              <div className="break-inside-avoid mb-8">
                <Section label="Personal">
                  <PersonalSection itemId={item.Id} showRewatchToggle />
                </Section>
              </div>
            )}
            {item.Id && !String(item.Id).startsWith('tmdb-') && (item.Type === 'Movie' || item.Type === 'Series') && prefs.detail.show.diary && (
              <div className="break-inside-avoid mb-8">
                <Section label="Diary">
                  <DiarySection itemId={item.Id} itemName={item.Name || 'Unknown'} />
                </Section>
              </div>
            )}
            {keywords.length > 0 && (
              <div className="break-inside-avoid mb-8">
                <Section label="Keywords">
                  <div className="flex flex-wrap gap-1.5">
                    {keywords.slice(0, 24).map(k => (
                      <span
                        key={k.id}
                        className="inline-flex items-center gap-1 h-6 px-2.5 bg-elevated/50 hover:bg-elevated border border-border hover:border-border-hover rounded-full text-[11px] text-text-2 hover:text-text-1 transition-colors cursor-default"
                      >
                        <Tag size={9} className="text-text-4" />
                        {k.name}
                      </span>
                    ))}
                  </div>
                </Section>
              </div>
            )}
          </div>
        )}

        {/* Collection - the franchise / series strip */}
        {tmdbMovieData?.belongs_to_collection && (
          <Section label="Collection">
            <CollectionStrip
              collectionRef={tmdbMovieData.belongs_to_collection}
              collection={tmdbCollectionData ?? undefined}
              currentMovieId={tmdbMovieData.id}
            />
          </Section>
        )}

        {/* Reviews */}
        {reviews.length > 0 && (
          <Section label="Reviews" id="detail-reviews">
            <ReviewsSection reviews={reviews} />
          </Section>
        )}
      </div>

      <section id="detail-more" className="scroll-mt-4 mt-14 pt-8 border-t border-border/60">
        <div className="px-7 mb-6">
          <div className="flex items-center gap-2 mb-1.5">
            <span className="w-1 h-3.5 rounded-full bg-accent" />
            <span className="text-[11px] font-semibold text-text-2 uppercase tracking-[0.14em]">
              More like this
            </span>
          </div>
          <p className="text-[12.5px] text-text-3 max-w-xl">
            Titles by the same people on this project plus algorithmic picks
            you might want to queue up next.
          </p>
        </div>

        <div className="space-y-2">
          {/* "From the same..." rows: highlight other work by the headline
              creator + a top-billed actor before the generic Discovery rows.
              Each row self-hides when the person has fewer than 3 other
              credits in the same media kind, so this stays scoped. */}
          {(itemType === 'Movie' || itemType === 'Series') && (
            <FromSameRowsCluster
              itemType={itemType}
              tmdbId={tmdbId}
              cast={cast}
              crew={crew}
              libraryMap={libraryMap}
            />
          )}

          {/* Discovery rows - library matches first, then full lists */}
          <DiscoveryRows
            recommendations={recommendations}
            similar={similar}
            libraryMap={libraryMap}
          />
        </div>
      </section>
    </>
  )
}

/**
 * Picks the headline director (or series creator) + the top-billed
 * actor from the credits and renders a FromSameRow for each. Skips
 * either row when there's nothing useful to render.
 */
function FromSameRowsCluster({
  itemType,
  tmdbId,
  cast,
  crew,
  libraryMap,
}: {
  itemType: string
  tmdbId: string | null | undefined
  cast: unknown[]
  crew: unknown[]
  libraryMap: Map<string, { id: string; name: string; type: string }> | undefined
}) {
  const kind: 'movie' | 'tv' = itemType === 'Series' ? 'tv' : 'movie'
  const crewList = crew as Array<{ id: number; name: string; job?: string; department?: string }>
  const castList = cast as Array<{ id: number; name: string; order?: number }>

  const director = crewList.find(c => c.job === 'Director')
  // For series, "Director" is rarely meaningful (each episode has its
  // own); use the executive producer / creator chain instead.
  const creator = kind === 'tv'
    ? crewList.find(c => c.job === 'Executive Producer' || c.job === 'Creator')
    : null
  const headlinePerson = director || creator
  const topActor = [...castList].sort((a, b) => (a.order ?? 999) - (b.order ?? 999))[0]

  const excludeId = tmdbId ? Number(tmdbId) : null

  return (
    <>
      {headlinePerson && (
        <FromSameRow
          personId={headlinePerson.id}
          personName={headlinePerson.name}
          role={director ? 'director' : 'writer'}
          excludeTmdbId={excludeId}
          kind={kind}
          libraryMap={libraryMap}
        />
      )}
      {topActor && (
        <FromSameRow
          personId={topActor.id}
          personName={topActor.name}
          role="actor"
          excludeTmdbId={excludeId}
          kind={kind}
          libraryMap={libraryMap}
        />
      )}
    </>
  )
}
