'use server'

import { redirect } from 'next/navigation'
import { cookies, headers } from 'next/headers'
import { getIronSession } from 'iron-session'
import { z } from 'zod'
import { prisma } from '@/lib/prisma'
import { registerUser, verifyUser, hashPassword } from '@/lib/auth'
import { SessionData, sessionOptions } from '@/lib/session'
import { checkRateLimit } from '@/lib/rate-limit'
import { isPhoneUA } from '@/lib/user-agent'
import { requireSession } from '@/lib/auth-guard'

async function getClientIp(): Promise<string> {
  const h = await headers()
  return h.get('x-forwarded-for')?.split(',')[0].trim() ?? h.get('x-real-ip') ?? 'unknown'
}

const registerSchema = z.object({
  username: z.string().min(3, 'Gebruikersnaam moet minimaal 3 tekens bevatten').max(50),
  password: z.string().min(8, 'Wachtwoord moet minimaal 8 tekens bevatten'),
})

const loginSchema = z.object({
  username: z.string().min(1),
  password: z.string().min(1),
})

export async function registerAction(_prevState: unknown, formData: FormData) {
  const ip = await getClientIp()
  if (!checkRateLimit(`register:${ip}`)) {
    return { error: 'Te veel pogingen. Probeer het over een minuut opnieuw.' }
  }

  const parsed = registerSchema.safeParse({
    username: formData.get('username'),
    password: formData.get('password'),
  })

  if (!parsed.success) {
    return { error: parsed.error.flatten().fieldErrors }
  }

  const result = await registerUser(parsed.data.username, parsed.data.password)
  if (result.error) return { error: result.error }

  const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
  session.userId = result.user!.id
  session.isDemo = false
  session.isAdmin = false
  await session.save()

  redirect('/dashboard')
}

export async function loginAction(_prevState: unknown, formData: FormData) {
  const ip = await getClientIp()
  if (!checkRateLimit(`login:${ip}`)) {
    return { error: 'Te veel inlogpogingen. Probeer het over een minuut opnieuw.' }
  }

  const parsed = loginSchema.safeParse({
    username: formData.get('username'),
    password: formData.get('password'),
  })

  if (!parsed.success) {
    return { error: 'Ongeldige inloggegevens' }
  }

  const user = await verifyUser(parsed.data.username, parsed.data.password)
  if (!user) {
    return { error: 'Onjuiste gebruikersnaam of wachtwoord' }
  }

  const adminRole = await prisma.userRole.findFirst({
    where: { user_id: user.id, role: 'ADMIN' },
  })
  const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
  session.userId = user.id
  session.isDemo = user.is_demo
  session.isAdmin = !!adminRole
  await session.save()

  // PBI-11 / ST-1135: telefoon-UA's krijgen de mobile-shell.
  // Tablets en desktop volgen het bestaande /dashboard-pad.
  const ua = (await headers()).get('user-agent')
  if (isPhoneUA(ua)) {
    redirect(user.active_product_id ? `/m/products/${user.active_product_id}/solo` : '/m/settings')
  }

  redirect('/dashboard')
}

export async function logoutAction() {
  const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
  session.destroy()
  redirect('/login')
}

const resetPasswordSchema = z
  .object({
    password: z.string().min(8, 'Wachtwoord moet minimaal 8 tekens bevatten'),
    confirm: z.string(),
  })
  .superRefine((data, ctx) => {
    if (data.password !== data.confirm) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: 'Wachtwoorden komen niet overeen',
        path: ['confirm'],
      })
    }
  })

export async function resetPasswordAction(_prevState: unknown, formData: FormData) {
  const session = await requireSession()

  const parsed = resetPasswordSchema.safeParse({
    password: formData.get('password'),
    confirm: formData.get('confirm'),
  })

  if (!parsed.success) {
    return { error: parsed.error.flatten().fieldErrors }
  }

  const hash = await hashPassword(parsed.data.password)
  await prisma.user.update({
    where: { id: session.userId },
    data: { password_hash: hash, must_reset_password: false },
  })

  redirect('/dashboard')
}
