// DocsSessionIndex.jsx — v0.21.0 (was v0.20.0 / roadmap item #30).
//
// Per-session landing at `/docs/sessions/:nnnn`. v0.20.0 rendered a
// dead-end "N transcript(s) in this session. Select one from the
// navigation." placeholder. v0.21.0 / roadmap item #32 collapses that:
// the session root now renders a transcript INLINE so the URL is never
// an empty stop.
//
//   - Exactly one transcript  → render it inline at the session root.
//   - Multiple transcripts    → render the `.0` driver transcript
//                               inline (fall back to the first file by
//                               sort order if there's no `.0`), AND
//                               list/link the remaining transcripts so
//                               the siblings are one click away.
//
// The URL stays stable to the session number — this is an inline
// render, not a 301/redirect. The per-transcript route
// (`/docs/sessions/:nnnn/:filename`) still exists and is what the
// sibling links and the left-nav transcript rows point at.
//
// The transcript count + filenames come from `/api/docs/sessions/:nnnn/index`
// so the empty-state ("no transcripts yet"), not-found, and error
// paths remain meaningful when the upstream is mid-publish or
// unreachable. The metadata header + body rendering are imported from
// DocsSessionTranscript.jsx so the inline view is byte-identical to the
// standalone per-transcript view.

import { useEffect, useState, useCallback } from 'react'
import { Link, useParams } from 'react-router-dom'
import MarkdownPreview from './MarkdownPreview.jsx'
import {
  getSessionsManifest,
  getSessionIndex,
  getSessionTranscript,
} from '../api.js'
import {
  TranscriptMetaHeader,
  transcriptOrdinal,
} from './DocsSessionTranscript.jsx'
import { EVENTS, track } from '../lib/analytics'
import './Docs.css'

// Pick the transcript to render inline at the session root: prefer the
// `.0` driver transcript; otherwise the first file by sort order. The
// backend already returns the file list sorted, so `files[0]` is a
// stable fallback.
function pickPrimary(files) {
  if (!files || files.length === 0) return null
  const driver = files.find(f => /^SESSION-\d{4}\.0-TRANSCRIPT/.test(f))
  return driver || files[0]
}

export default function DocsSessionIndex() {
  const { nnnn } = useParams()
  const [title, setTitle] = useState('')
  const [tldr, setTldr] = useState('')
  const [files, setFiles] = useState([])
  const [status, setStatus] = useState('loading') // loading | ok | notfound | error
  const [reloadTick, setReloadTick] = useState(0)

  // The inline body for the primary transcript.
  const [body, setBody] = useState('')
  const [bodyStatus, setBodyStatus] = useState('idle') // idle | loading | ok | notfound | error

  useEffect(() => {
    track(EVENTS.DOC_VIEWED, { section: `sessions/${nnnn}` })
  }, [nnnn])

  // Title + optional TL;DR from the manifest — cheap, cached server-side.
  useEffect(() => {
    let active = true
    getSessionsManifest()
      .then(payload => {
        if (!active) return
        const entry = (payload && payload[nnnn]) || {}
        setTitle(entry.title || '')
        // `tldr` is an optional manifest field (string). Absent ⇒ the
        // header renders no TL;DR line (graceful degrade).
        setTldr(typeof entry.tldr === 'string' ? entry.tldr : '')
      })
      .catch(() => {
        // Title + TL;DR are decorative; the transcript list + body
        // fetches below are the load-bearing ones.
      })
    return () => { active = false }
  }, [nnnn])

  // File list from the per-session index endpoint.
  useEffect(() => {
    let active = true
    setStatus('loading')
    getSessionIndex(nnnn)
      .then(payload => {
        if (!active) return
        setFiles((payload && payload.files) || [])
        setStatus('ok')
      })
      .catch(e => {
        if (!active) return
        if (e.status === 404) {
          setStatus('notfound')
        } else {
          setStatus('error')
        }
      })
    return () => { active = false }
  }, [nnnn, reloadTick])

  const primary = status === 'ok' ? pickPrimary(files) : null

  // Fetch the primary transcript body once we know which file it is.
  useEffect(() => {
    if (!primary) {
      setBody('')
      setBodyStatus('idle')
      return
    }
    let active = true
    setBodyStatus('loading')
    getSessionTranscript(nnnn, primary)
      .then(text => {
        if (!active) return
        setBody(text || '')
        setBodyStatus('ok')
      })
      .catch(e => {
        if (!active) return
        setBodyStatus(e.status === 404 ? 'notfound' : 'error')
      })
    return () => { active = false }
  }, [nnnn, primary, reloadTick])

  const retry = useCallback(() => setReloadTick(t => t + 1), [])

  const header = title ? `${nnnn} — ${title}` : `Session ${nnnn}`
  const siblings = primary ? files.filter(f => f !== primary) : []

  return (
    <article className="docs-article">
      <h1 className="docs-article-title">{header}</h1>

      {status === 'loading' && <p className="muted">Loading…</p>}

      {status === 'notfound' && (
        <div className="docs-empty">
          <p>
            No transcripts have been published for this session yet.{' '}
            <Link
              to="/docs/sessions/about"
              aria-label="About sessions"
              data-amp-track-name="Docs Session Empty About Link"
            >
              About sessions
            </Link>
          </p>
        </div>
      )}

      {status === 'error' && (
        <div className="docs-error" role="alert">
          <p>Couldn't reach the session-history repo.</p>
          <button
            type="button"
            onClick={retry}
            aria-label="Retry"
            data-amp-track-name="Docs Session Index Retry"
          >
            Try again
          </button>
        </div>
      )}

      {status === 'ok' && files.length === 0 && (
        <div className="docs-empty">
          <p>This session has no transcripts published.</p>
        </div>
      )}

      {status === 'ok' && primary && (
        <>
          {siblings.length > 0 && (
            <nav className="docs-session-siblings" aria-label="Transcripts in this session">
              <span className="docs-session-siblings-label">Transcripts</span>
              <ul className="docs-session-siblings-list">
                <li>
                  <span
                    className="docs-session-siblings-current"
                    aria-current="true"
                  >
                    {transcriptOrdinal(primary)} (shown below)
                  </span>
                </li>
                {siblings.map(f => (
                  <li key={f}>
                    <Link
                      to={`/docs/sessions/${nnnn}/${f}`}
                      aria-label={`Transcript ${transcriptOrdinal(f)}`}
                      data-amp-track-name="Docs Session Sibling Transcript"
                      data-amp-track-session={nnnn}
                      data-amp-track-filename={f}
                    >
                      {transcriptOrdinal(f)}
                    </Link>
                  </li>
                ))}
              </ul>
            </nav>
          )}

          {bodyStatus === 'loading' && <p className="muted">Loading transcript…</p>}
          {bodyStatus === 'notfound' && (
            <div className="docs-empty">
              <p>This transcript isn't published yet.</p>
            </div>
          )}
          {bodyStatus === 'error' && (
            <div className="docs-error" role="alert">
              <p>Couldn't reach the session-history repo.</p>
              <button
                type="button"
                onClick={retry}
                aria-label="Retry"
                data-amp-track-name="Docs Session Inline Retry"
              >
                Try again
              </button>
            </div>
          )}
          {bodyStatus === 'ok' && (
            <>
              <TranscriptMetaHeader
                nnnn={nnnn}
                filename={primary}
                title={title}
                tldr={tldr}
              />
              <div className="philosophy-body">
                <MarkdownPreview content={body} />
              </div>
            </>
          )}
        </>
      )}
    </article>
  )
}
