import { notFound, redirect } from 'next/navigation'
import { getSession } from '@/lib/auth'
import { getAccessibleProduct } from '@/lib/product-access'
import { prisma } from '@/lib/prisma'
import { pbiStatusToApi } from '@/lib/task-status'
import { SprintBoardClient } from '@/components/sprint/sprint-board-client'
import {
  SprintHydrationWrapper,
  type SprintHydrationData,
} from '@/components/sprint/sprint-hydration-wrapper'
import { SprintTaskDialogMount } from '@/components/sprint/sprint-task-dialog-mount'
import { SprintUrlTaskSync } from '@/components/sprint/sprint-url-task-sync'
import { SyncActiveSprintCookie } from '@/components/sprint/sync-active-sprint-cookie'
import { getSprintSwitcherData } from '@/lib/sprint-switcher-data'
import { SprintHeader } from '@/components/sprint/sprint-header'
import { SprintRunControls } from '@/components/sprint/sprint-run-controls'
import { parsePauseContext } from '@/lib/pause-context'
import type { SprintStory, PbiWithStories, ProductMember } from '@/components/sprint/sprint-backlog'
import type { SprintWorkspaceTask } from '@/stores/sprint-workspace/types'
import { TaskDialog } from '@/app/_components/tasks/task-dialog'
import Link from 'next/link'

interface Props {
  params: Promise<{ id: string; sprintId: string }>
  searchParams: Promise<{
    newTask?: string
    storyId?: string
  }>
}

export default async function SprintBoardPage({ params, searchParams }: Props) {
  const { id, sprintId } = await params
  const { newTask, storyId: storyIdParam } = await searchParams

  const session = await getSession()
  if (!session.userId) redirect('/login')

  const product = await getAccessibleProduct(id, session.userId)
  if (!product) notFound()

  const sprint = await prisma.sprint.findFirst({
    where: { id: sprintId, product_id: id },
    select: {
      id: true,
      code: true,
      sprint_goal: true,
      status: true,
      start_date: true,
      end_date: true,
    },
  })
  if (!sprint) notFound()

  const switcherData = await getSprintSwitcherData(id, { activeSprintId: sprint.id })

  const activeSprintRun = await prisma.sprintRun.findFirst({
    where: {
      sprint_id: sprint.id,
      status: { in: ['QUEUED', 'RUNNING', 'PAUSED'] },
    },
    select: { id: true, status: true, pause_context: true },
    orderBy: { created_at: 'desc' },
  })
  const pauseContext =
    activeSprintRun?.status === 'PAUSED'
      ? parsePauseContext(activeSprintRun.pause_context)
      : null

  // Sprint stories with full task data and assignee
  const [sprintStories, productMembers] = await Promise.all([
    prisma.story.findMany({
      where: { sprint_id: sprint.id },
      orderBy: { sort_order: 'asc' },
      include: {
        tasks: { orderBy: [{ sort_order: 'asc' }] },
        assignee: { select: { id: true, username: true } },
      },
    }),
    prisma.productMember.findMany({
      where: { product_id: id },
      include: { user: { select: { id: true, username: true } } },
    }),
  ])

  // All members who can be assigned: owner + product members
  const members: ProductMember[] = [
    { userId: product.user_id, username: (await prisma.user.findUnique({ where: { id: product.user_id }, select: { username: true } }))?.username ?? 'Eigenaar' },
    ...productMembers.map(m => ({ userId: m.user_id, username: m.user.username })),
  ]

  const sprintStoryItems: SprintStory[] = sprintStories.map(s => ({
    id: s.id,
    code: s.code,
    title: s.title,
    description: s.description,
    acceptance_criteria: s.acceptance_criteria,
    pbi_id: s.pbi_id,
    sprint_id: s.sprint_id,
    created_at: s.created_at,
    priority: s.priority,
    sort_order: s.sort_order,
    status: s.status,
    taskCount: s.tasks.length,
    doneCount: s.tasks.filter(t => t.status === 'DONE').length,
    assignee_id: s.assignee_id,
    assignee_username: s.assignee?.username ?? null,
  }))

  const tasksByStoryWorkspace: Record<string, SprintWorkspaceTask[]> = {}
  for (const story of sprintStories) {
    tasksByStoryWorkspace[story.id] = story.tasks.map(t => ({
      id: t.id,
      code: t.code,
      title: t.title,
      description: t.description,
      priority: t.priority,
      sort_order: t.sort_order,
      status: t.status,
      story_id: t.story_id,
      sprint_id: t.sprint_id,
      created_at: t.created_at,
    }))
  }

  // All PBIs with their stories for the left (product backlog) panel
  const pbis = await prisma.pbi.findMany({
    where: { product_id: id },
    orderBy: [{ priority: 'asc' }, { sort_order: 'asc' }],
    include: {
      stories: {
        orderBy: [{ sort_order: 'asc' }],
      },
    },
  })

  const pbisWithStories: PbiWithStories[] = pbis
    .filter(pbi => pbi.stories.length > 0)
    .map(pbi => ({
      id: pbi.id,
      code: pbi.code,
      title: pbi.title,
      priority: pbi.priority,
      status: pbiStatusToApi(pbi.status),
      description: pbi.description,
      stories: pbi.stories.map(s => ({
        id: s.id,
        code: s.code,
        title: s.title,
        description: s.description,
        acceptance_criteria: s.acceptance_criteria,
        pbi_id: s.pbi_id,
        sprint_id: s.sprint_id,
        created_at: s.created_at,
        priority: s.priority,
        sort_order: s.sort_order,
        status: s.status,
        taskCount: 0,
        doneCount: 0,
        assignee_id: null,
        assignee_username: null,
      })),
    }))

  const isDemo = session.isDemo ?? false
  const closePath = `/products/${id}/sprint/${sprint.id}`

  const hydrationData: SprintHydrationData = {
    sprint: {
      id: sprint.id,
      product_id: id,
      code: sprint.code,
      sprint_goal: sprint.sprint_goal,
      status: sprint.status as 'OPEN' | 'CLOSED',
      start_date: sprint.start_date ? sprint.start_date.toISOString().slice(0, 10) : null,
      end_date: sprint.end_date ? sprint.end_date.toISOString().slice(0, 10) : null,
      created_at: new Date(),
      completed_at: null,
    },
    stories: sprintStoryItems,
    tasksByStory: tasksByStoryWorkspace,
  }

  return (
    <div id="wrapper2" className="flex flex-col h-full">
      <SyncActiveSprintCookie productId={id} sprintId={sprint.id} />
      <SprintHeader
        productId={id}
        productName={product.name}
        sprint={sprint}
        isDemo={isDemo}
        sprintStories={sprintStoryItems}
        switcherSprints={switcherData.sprintItems}
        switcherActiveSprint={switcherData.activeSprintItem}
        switcherBuildingSprintIds={switcherData.buildingSprintIds}
      />

      <div className="border-b border-border bg-surface-container-low px-4 py-2 shrink-0">
        <SprintRunControls
          sprintId={sprint.id}
          productId={id}
          sprintStatus={sprint.status}
          activeSprintRunId={activeSprintRun?.id ?? null}
          activeSprintRunStatus={activeSprintRun?.status ?? null}
          pauseContext={pauseContext}
          isDemo={isDemo}
        />
      </div>

      <div className="flex-1 overflow-hidden">
        <SprintHydrationWrapper
          initialData={hydrationData}
          productId={id}
          productName={product.name}
        >
          <SprintBoardClient
            key={sprint.id}
            productId={id}
            sprintId={sprint.id}
            pbisWithStories={pbisWithStories}
            isDemo={isDemo}
            currentUserId={session.userId}
            members={members}
          />
          <SprintTaskDialogMount productId={id} isDemo={isDemo} />
          <SprintUrlTaskSync />
        </SprintHydrationWrapper>
      </div>

      <div className="border-t border-border px-4 py-2 bg-surface-container-low shrink-0">
        <Link href={`/products/${id}`} className="text-sm text-muted-foreground hover:text-foreground">
          ← Product Backlog
        </Link>
      </div>

      {newTask && (
        <TaskDialog
          storyId={storyIdParam}
          productId={id}
          closePath={closePath}
          isDemo={isDemo}
        />
      )}
    </div>
  )
}
