'use server'

import { revalidatePath } from 'next/cache'
import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { z } from 'zod'
import type { Prisma } from '@prisma/client'
import { prisma } from '@/lib/prisma'
import { SessionData, sessionOptions } from '@/lib/session'
import { productAccessFilter } from '@/lib/product-access'
import {
  mergeSettings,
  parseUserSettings,
  type PendingSprintDraft,
  type UserSettings,
} from '@/lib/user-settings'

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

const StoryOverridesSchema = z.object({
  add: z.array(z.string()),
  remove: z.array(z.string()),
}).strict()

const DraftSchema = z.object({
  goal: z.string().min(1),
  startAt: z.string().date().optional(),
  endAt: z.string().date().optional(),
  pbiIntent: z.record(z.string(), z.enum(['all', 'none'])).default({}),
  storyOverrides: z.record(z.string(), StoryOverridesSchema).default({}),
}).strict()

const SetSchema = z.object({
  productId: z.string().min(1),
  draft: DraftSchema,
})

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

async function ensureProductAccess(userId: string, productId: string) {
  return prisma.product.findFirst({
    where: { id: productId, ...productAccessFilter(userId) },
    select: { id: true },
  })
}

async function readUserSettings(userId: string): Promise<UserSettings> {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    select: { settings: true },
  })
  return parseUserSettings(user?.settings)
}

async function writeUserSettings(userId: string, next: UserSettings) {
  await prisma.user.update({
    where: { id: userId },
    data: { settings: next as unknown as Prisma.InputJsonValue },
  })
}

export async function setPendingSprintDraftAction(
  productId: string,
  draft: PendingSprintDraft,
) {
  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, draft })
  if (!parsed.success) {
    return { error: 'Ongeldige draft', issues: parsed.error.issues }
  }

  const product = await ensureProductAccess(session.userId, parsed.data.productId)
  if (!product) return { error: 'Product niet gevonden of niet toegankelijk' }

  const current = await readUserSettings(session.userId)
  const patch: Partial<UserSettings> = {
    workflow: {
      pendingSprintDraft: {
        ...(current.workflow?.pendingSprintDraft ?? {}),
        [parsed.data.productId]: parsed.data.draft,
      },
    },
  }
  await writeUserSettings(session.userId, mergeSettings(current, patch))
  revalidatePath('/', 'layout')
  return { success: true }
}

export async function clearPendingSprintDraftAction(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 ensureProductAccess(session.userId, parsed.data.productId)
  if (!product) return { error: 'Product niet gevonden of niet toegankelijk' }

  const current = await readUserSettings(session.userId)
  const existingMap = current.workflow?.pendingSprintDraft
  if (!existingMap || !(parsed.data.productId in existingMap)) {
    return { success: true }
  }
  const nextMap = { ...existingMap }
  delete nextMap[parsed.data.productId]
  const next: UserSettings = {
    ...current,
    workflow: { ...current.workflow, pendingSprintDraft: nextMap },
  }
  await writeUserSettings(session.userId, next)
  revalidatePath('/', 'layout')
  return { success: true }
}
