import Link from 'next/link'
import { notFound, redirect } from 'next/navigation'
import { db } from '@/lib/db'
import { requireStudent } from '@/lib/auth'
import { Card } from '@/components/ui'
import { ItemForm } from './form'
import { ExplanationPanel, HintPanel, StuckButton } from './stuck'
import { SetReview } from './review'
import { MAX_HINTS } from '@/lib/prompts'

export default async function TakeSet({
  params,
  searchParams,
}: {
  params: Promise<{ setId: string }>
  searchParams: Promise<{ explain?: string }>
}) {
  const { setId } = await params
  const { explain } = await searchParams
  const session = await requireStudent()

  const set = await db.itemSet.findUnique({
    where: { id: setId },
    include: {
      items: {
        // An item the reviewer withheld is never served to him. It stays in the
        // set for Eric to see and restore, but it is not part of the sitting.
        where: { droppedByReviewer: false },
        orderBy: { position: 'asc' },
        include: {
          item: true,
          hints: { orderBy: { askedAt: 'asc' } },
          response: { include: { questions: { orderBy: { askedAt: 'asc' } } } },
        },
      },
    },
  })
  if (!set) notFound()
  if (set.studentId !== session.id) redirect('/student')
  // A draft or discarded set must never be reachable by a boy.
  if (!['RELEASED', 'IN_PROGRESS', 'COMPLETE'].includes(set.status)) redirect('/student')

  // The clock starts when he opens it, not when he submits the first answer —
  // otherwise the first item's thinking time is invisible, and that is often
  // the item he spends longest on. Idempotent: only fires on the first open.
  if (set.status === 'RELEASED') {
    await db.itemSet.update({
      where: { id: set.id },
      data: { status: 'IN_PROGRESS', startedAt: new Date() },
    })
    set.startedAt = new Date()
    set.status = 'IN_PROGRESS'
  }

  const next = set.items.find((si) => !si.response)
  const answered = set.items.filter((si) => si.response).length

  // After conceding he stays on that item — reading the explanation, asking
  // about it — until he chooses to move on. Held in the URL rather than in a
  // column, so "come back to it later" is just a link.
  const explaining = explain
    ? set.items.find((si) => si.id === explain && si.response?.conceded)
    : undefined

  if (explaining?.response) {
    return (
      <div className="space-y-4">
        <div className="flex items-baseline justify-between">
          <h1 className="text-base font-medium">{set.title}</h1>
          <span className="text-xs text-[var(--color-muted)]">
            {answered} of {set.items.length}
          </span>
        </div>

        <Card>
          <p className="text-[15px] leading-relaxed whitespace-pre-wrap">
            {explaining.item.prompt}
          </p>
        </Card>

        <ExplanationPanel
          responseId={explaining.response.id}
          explanation={explaining.item.explanation}
          questions={explaining.response.questions.map((q) => ({
            id: q.id,
            question: q.question,
            answer: q.answer,
            status: q.status,
          }))}
          onDone={`/student/take/${set.id}`}
        />
      </div>
    )
  }

  if (!next) {
    // Everything he needs is already here: the explanations were written when
    // the set was generated, so he can read back how each one worked while it
    // is still fresh, rather than waiting on grading.
    const awaitingFeedback = set.items.some((si) => si.response && !si.response.feedbackForStudent)
    return (
      <div className="space-y-4">
        <Card className="space-y-2">
          <h1 className="text-base font-medium">{set.title} — all done</h1>
          <p className="text-sm text-[var(--color-muted)]">
            Thanks for taking your time on it. Have a look back through them below
            &mdash; you can open up how each one worked, and ask me about any of them.
            {awaitingFeedback && ' A note on each one is on its way; it takes a few minutes.'}
          </p>
        </Card>

        <SetReview
          gradingInProgress={awaitingFeedback}
          items={set.items
            .filter((si) => si.response)
            .map((si) => ({
              position: si.position + 1,
              prompt: si.item.prompt,
              stimulus: si.item.stimulus,
              explanation: si.item.explanation,
              responseId: si.response!.id,
              typedText: si.response!.typedText,
              choiceKey: si.response!.choiceKey,
              answerKey: si.item.answerKey,
              imageCount: Array.isArray(si.response!.imagePaths)
                ? (si.response!.imagePaths as string[]).length
                : 0,
              conceded: si.response!.conceded,
              hintsUsed: si.response!.hintsUsed,
              feedback: si.response!.feedbackForStudent,
              questions: si.response!.questions.map((q) => ({
                id: q.id,
                question: q.question,
                answer: q.answer,
                status: q.status,
              })),
            }))}
        />

        <Link href="/student" className="block text-sm text-[var(--color-muted)] hover:underline">
          &larr; Back
        </Link>
      </div>
    )
  }

  return (
    <div className="space-y-4">
      <div className="flex items-baseline justify-between">
        <h1 className="text-base font-medium">{set.title}</h1>
        <span className="text-xs text-[var(--color-muted)]">
          {answered + 1} of {set.items.length}
        </span>
      </div>

      <ItemForm
        setItemId={next.id}
        item={{
          stimulus: next.item.stimulus,
          prompt: next.item.prompt,
          choices: next.item.choices as { key: string; text: string }[] | null,
          format: next.item.format,
          responseMode: next.item.responseMode,
        }}
      />

      <HintPanel
        setItemId={next.id}
        maxHints={MAX_HINTS}
        hints={next.hints.map((h) => ({
          id: h.id,
          question: h.question,
          hint: h.hint,
          status: h.status,
        }))}
      />

      <StuckButton setItemId={next.id} />

      <p className="text-center text-xs text-[var(--color-muted)]">
        Take as long as you want. There&rsquo;s no timer.
      </p>
    </div>
  )
}
