'use server'

import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { Prisma } from '@prisma/client'
import { prisma } from '@/lib/prisma'
import { SessionData, sessionOptions } from '@/lib/session'
import {
  UserSettingsSchema,
  mergeSettings,
  parseUserSettings,
  type UserSettings,
} from '@/lib/user-settings'

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

export type UpdateUserSettingsResult =
  | { success: true; settings: UserSettings }
  | { error: string; code: 401 | 403 | 422; fieldErrors?: Record<string, string[]> }

export async function updateUserSettingsAction(
  patch: Partial<UserSettings>,
): Promise<UpdateUserSettingsResult> {
  const session = await getSession()
  if (!session.userId) return { error: 'Niet ingelogd', code: 401 }
  if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus', code: 403 }

  const parsed = UserSettingsSchema.partial().safeParse(patch)
  if (!parsed.success) {
    return {
      error: 'Ongeldige settings-patch',
      code: 422,
      fieldErrors: parsed.error.flatten().fieldErrors as Record<string, string[]>,
    }
  }

  const merged = await prisma.$transaction(async (tx) => {
    const user = await tx.user.findUnique({
      where: { id: session.userId! },
      select: { settings: true },
    })
    const current = parseUserSettings(user?.settings)
    const next = mergeSettings(current, parsed.data)
    await tx.user.update({
      where: { id: session.userId! },
      data: { settings: next as unknown as Prisma.InputJsonValue },
    })
    return next
  })

  await prisma.$executeRaw`
    SELECT pg_notify('scrum4me_changes', ${JSON.stringify({
      kind: 'user_settings',
      userId: session.userId,
      patch: parsed.data,
    })}::text)
  `

  return { success: true, settings: merged }
}
