'use server'

import { revalidatePath } from 'next/cache'
import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { z } from 'zod'
import { prisma } from '@/lib/prisma'
import { SessionData, sessionOptions } from '@/lib/session'
import { productAccessFilter } from '@/lib/product-access'
import {
  clearActiveSprintInSettings,
  setActiveSelectionInSettings,
  setActiveSprintInSettings,
} from '@/lib/active-sprint'

async function getSession() {
  return getIronSession<SessionData>(await cookies(), sessionOptions)
}

const setSchema = z.object({
  productId: z.string().min(1),
  sprintId: z.string().min(1),
})

const clearSchema = z.object({
  productId: z.string().min(1),
})

export async function setActiveSprintAction(productId: string, sprintId: string) {
  const session = await getSession()
  if (!session.userId) return { error: 'Niet ingelogd' }
  if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' }

  const parsed = setSchema.safeParse({ productId, sprintId })
  if (!parsed.success) return { error: 'Ongeldig product- of sprint-id' }

  const sprint = await prisma.sprint.findFirst({
    where: {
      id: parsed.data.sprintId,
      product_id: parsed.data.productId,
      product: productAccessFilter(session.userId),
    },
    select: { id: true },
  })
  if (!sprint) return { error: 'Sprint niet gevonden of niet toegankelijk' }

  await setActiveSprintInSettings(session.userId, parsed.data.productId, parsed.data.sprintId)
  revalidatePath('/', 'layout')
  return { success: true, sprintId: parsed.data.sprintId }
}

export async function clearActiveSprintAction(productId: string) {
  const session = await getSession()
  if (!session.userId) return { error: 'Niet ingelogd' }
  if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' }

  const parsed = clearSchema.safeParse({ productId })
  if (!parsed.success) return { error: 'Ongeldig product-id' }

  const product = await prisma.product.findFirst({
    where: { id: parsed.data.productId, ...productAccessFilter(session.userId) },
    select: { id: true },
  })
  if (!product) return { error: 'Product niet gevonden of niet toegankelijk' }

  await clearActiveSprintInSettings(session.userId, parsed.data.productId)
  revalidatePath('/', 'layout')
  return { success: true }
}

const selectionSchema = z.object({
  productId: z.string().min(1),
  sprintId: z.string().min(1),
})

/**
 * PBI-79: kies een sprint en auto-select zijn enige PBI/story (indien
 * singleton). Resultaat wordt server-side bepaald + atomair in user-settings
 * weggeschreven (sprint+pbi+story) zodat cross-device-restore klopt.
 */
export async function switchActiveSprintAction(
  productId: string,
  sprintId: string,
): Promise<
  | {
      success: true
      sprintId: string
      pbiId: string | null
      storyId: string | null
    }
  | { error: string }
> {
  const session = await getSession()
  if (!session.userId) return { error: 'Niet ingelogd' }
  if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' }

  const parsed = selectionSchema.safeParse({ productId, sprintId })
  if (!parsed.success) return { error: 'Ongeldig product- of sprint-id' }

  const sprint = await prisma.sprint.findFirst({
    where: {
      id: parsed.data.sprintId,
      product_id: parsed.data.productId,
      product: productAccessFilter(session.userId),
    },
    select: { id: true },
  })
  if (!sprint) return { error: 'Sprint niet gevonden of niet toegankelijk' }

  // Auto-select: alleen wanneer sprint exact één PBI heeft. Story-auto-select
  // alleen wanneer die PBI exact één story binnen deze sprint heeft.
  const sprintStories = await prisma.story.findMany({
    where: {
      sprint_id: parsed.data.sprintId,
      product_id: parsed.data.productId,
    },
    select: { id: true, pbi_id: true },
  })
  const uniquePbiIds = Array.from(new Set(sprintStories.map((s) => s.pbi_id)))
  let autoPbiId: string | null = null
  let autoStoryId: string | null = null
  if (uniquePbiIds.length === 1) {
    autoPbiId = uniquePbiIds[0]
    const storiesForPbi = sprintStories.filter((s) => s.pbi_id === autoPbiId)
    if (storiesForPbi.length === 1) {
      autoStoryId = storiesForPbi[0].id
    }
  }

  await setActiveSelectionInSettings(session.userId, parsed.data.productId, {
    sprintId: parsed.data.sprintId,
    pbiId: autoPbiId,
    storyId: autoStoryId,
  })
  revalidatePath('/', 'layout')

  return {
    success: true,
    sprintId: parsed.data.sprintId,
    pbiId: autoPbiId,
    storyId: autoStoryId,
  }
}

export async function syncActiveSprintCookieAction(productId: string, sprintId: string) {
  const session = await getSession()
  if (!session.userId) return
  if (session.isDemo) return

  const parsed = setSchema.safeParse({ productId, sprintId })
  if (!parsed.success) return

  const sprint = await prisma.sprint.findFirst({
    where: {
      id: parsed.data.sprintId,
      product_id: parsed.data.productId,
      product: productAccessFilter(session.userId),
    },
    select: { id: true },
  })
  if (!sprint) return

  await setActiveSprintInSettings(session.userId, parsed.data.productId, parsed.data.sprintId)
}
