'use server'

import { prisma, Prisma } from '@innungsapp/shared'
import { auth, getSanitizedHeaders } from '@/lib/auth'
import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'
import { z } from 'zod'
import { sendAdminCredentialsEmail } from '@/lib/email'
// @ts-ignore
import { hashPassword } from 'better-auth/crypto'

function normalizeEmail(email: string | null | undefined): string {
  return (email ?? '').trim().toLowerCase()
}

function toJsonbText(value: string | undefined): Prisma.InputJsonValue | Prisma.NullableJsonNullValueInput {
  if (!value) {
    return Prisma.DbNull
  }

  return value
}

/**
 * Sets a credential (email+password) account for a user.
 * Uses direct DB write with better-auth's hashPassword for compatibility.
 */
async function setCredentialPassword(userId: string, password: string) {
  const hashedPassword = await hashPassword(password)
  const updated = await prisma.account.updateMany({
    where: { userId, providerId: 'credential' },
    data: { password: hashedPassword, accountId: userId },
  })
  if (updated.count === 0) {
    await prisma.account.create({
      data: {
        id: crypto.randomUUID(),
        userId,
        accountId: userId,
        providerId: 'credential',
        password: hashedPassword,
      },
    })
  }
}


async function requireSuperAdmin() {
  const session = await auth.api.getSession({ headers: await getSanitizedHeaders() })
  const superAdminEmail = process.env.SUPERADMIN_EMAIL || 'superadmin@innungsapp.de'

  // An admin is either specifically the superadmin email OR has the 'admin' role from better-auth admin plugin
  const isSuperAdmin = session?.user && (
    session.user.email === superAdminEmail ||
    (session.user as any).role === 'admin'
  )

  if (!isSuperAdmin) {
    return null
  }

  return session
}

const createOrgSchema = z.object({
  name: z.string().min(2, 'Name muss mindestens 2 Zeichen lang sein'),
  slug: z
    .string()
    .min(2, 'Slug muss mindestens 2 Zeichen lang sein')
    .regex(/^[a-z0-9-]+$/, 'Slug darf nur Kleinbuchstaben, Zahlen und Bindestriche enthalten'),
  contactEmail: z.string().email('Ungueltige E-Mail Adresse').optional().or(z.literal('')),
  adminEmail: z.string().email('Ungueltige Admin E-Mail').optional().or(z.literal('')),
  adminPassword: z.string().min(8, 'Passwort muss mindestens 8 Zeichen lang sein').optional().or(z.literal('')),
  logoUrl: z.string().optional().nullable(),
  plan: z.enum(['pilot', 'standard', 'pro', 'verband']).default('pilot'),
  primaryColor: z.string().regex(/^#([0-9a-fA-F]{6})$/, 'Ungueltige Farbe').optional().or(z.literal('')),
  secondaryColor: z.string().regex(/^#([0-9a-fA-F]{6})$/, 'Ungueltige Farbe').optional().or(z.literal('')),
  landingPageTitle: z.string().optional(),
  landingPageText: z.string().optional(),
  landingPageHeroImage: z.string().optional().nullable(),
  landingPageHeroOverlayOpacity: z.number().min(0).max(100).optional().default(50),
  landingPageFeatures: z.string().optional(),
  landingPageFooter: z.string().optional(),
  landingPageSectionTitle: z.string().optional(),
  landingPageButtonText: z.string().optional(),
  appStoreUrl: z.string().url('Ungueltige URL').optional().or(z.literal('')),
  playStoreUrl: z.string().url('Ungueltige URL').optional().or(z.literal('')),
})

const updateOrgSchema = z.object({
  name: z.string().min(2, 'Name muss mindestens 2 Zeichen lang sein'),
  plan: z.enum(['pilot', 'standard', 'pro', 'verband']),
  contactEmail: z.string().email('Ungueltige E-Mail Adresse').optional().or(z.literal('')),
  logoUrl: z.string().optional().nullable(),
  primaryColor: z.string().regex(/^#([0-9a-fA-F]{6})$/, 'Ungueltige Farbe').optional().or(z.literal('')),
  secondaryColor: z.string().regex(/^#([0-9a-fA-F]{6})$/, 'Ungueltige Farbe').optional().or(z.literal('')),
  landingPageTitle: z.string().optional(),
  landingPageText: z.string().optional(),
  landingPageHeroImage: z.string().optional().nullable(),
  landingPageFeatures: z.string().optional(),
  landingPageFooter: z.string().optional(),
  landingPageSectionTitle: z.string().optional(),
  landingPageButtonText: z.string().optional(),
  appStoreUrl: z.string().url('Ungueltige URL').optional().or(z.literal('')),
  playStoreUrl: z.string().url('Ungueltige URL').optional().or(z.literal('')),
})

const createAdminSchema = z.object({
  orgId: z.string(),
  name: z.string().min(2, 'Name ist zu kurz'),
  email: z.string().email('Ungueltige E-Mail Adresse'),
  password: z.string().min(8, 'Passwort muss mindestens 8 Zeichen lang sein'),
})

const createMemberSchema = z.object({
  orgId: z.string(),
  name: z.string().min(2, 'Name ist zu kurz'),
  email: z.string().email('Ungueltige E-Mail Adresse'),
  betrieb: z.string().min(2, 'Betrieb ist zu kurz'),
  sparte: z.string().min(2, 'Sparte ist zu kurz'),
  ort: z.string().min(2, 'Ort ist zu kurz'),
})

export async function createOrganization(prevState: any, formData: FormData) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  try {
    const rawData = {
      name: (formData.get('name') as string).trim(),
      slug: (formData.get('slug') as string).trim().toLowerCase(),
      contactEmail: (formData.get('contactEmail') as string).trim(),
      adminEmail: normalizeEmail(formData.get('adminEmail') as string),
      adminPassword: formData.get('adminPassword') as string,
      logoUrl: formData.get('logoUrl') as string,
      plan: (formData.get('plan') as string) || 'pilot',
      primaryColor: formData.get('primaryColor') as string,
      secondaryColor: formData.get('secondaryColor') as string,
      landingPageTitle: (formData.get('landingPageTitle') as string).trim(),
      landingPageText: (formData.get('landingPageText') as string).trim(),
      landingPageHeroImage: formData.get('landingPageHeroImage') as string,
      landingPageHeroOverlayOpacity: Number(formData.get('landingPageHeroOverlayOpacity') || '50'),
      landingPageFeatures: (formData.get('landingPageFeatures') as string).trim(),
      landingPageFooter: (formData.get('landingPageFooter') as string).trim(),
      landingPageSectionTitle: (formData.get('landingPageSectionTitle') as string || '').trim(),
      landingPageButtonText: (formData.get('landingPageButtonText') as string || '').trim(),
      appStoreUrl: (formData.get('appStoreUrl') as string || '').trim(),
      playStoreUrl: (formData.get('playStoreUrl') as string || '').trim(),
    }

    const validatedData = createOrgSchema.parse(rawData)

    const existingOrg = await prisma.organization.findUnique({
      where: { slug: validatedData.slug },
    })

    if (existingOrg) {
      return { success: false, error: 'Diese Kurzbezeichnung (Slug) existiert bereits.' }
    }

    const org = await prisma.organization.create({
      data: {
        name: validatedData.name,
        slug: validatedData.slug,
        contactEmail: validatedData.contactEmail || validatedData.adminEmail || null,
        plan: validatedData.plan,
        primaryColor: validatedData.primaryColor || '#E63946',
        secondaryColor: validatedData.secondaryColor || null,
        logoUrl: validatedData.logoUrl || null,
        landingPageTitle: validatedData.landingPageTitle || null,
        landingPageText: validatedData.landingPageText || null,
        landingPageHeroImage: validatedData.landingPageHeroImage || null,
        // @ts-ignore
        landingPageHeroOverlayOpacity: validatedData.landingPageHeroOverlayOpacity,
        landingPageFeatures: toJsonbText(validatedData.landingPageFeatures),
        landingPageFooter: toJsonbText(validatedData.landingPageFooter),
        landingPageSectionTitle: validatedData.landingPageSectionTitle || null,
        landingPageButtonText: validatedData.landingPageButtonText || null,
        appStoreUrl: validatedData.appStoreUrl || null,
        playStoreUrl: validatedData.playStoreUrl || null,
      },
    })

    if (validatedData.adminEmail) {
      let user = await prisma.user.findUnique({ where: { email: validatedData.adminEmail } })

      if (!user) {
        user = await prisma.user.create({
          data: {
            id: crypto.randomUUID(),
            name: validatedData.adminEmail.split('@')[0],
            email: validatedData.adminEmail,
            emailVerified: true,
            mustChangePassword: !!validatedData.adminPassword,
          },
        })
      } else {
        // If user exists, we still want to make sure they are verified and maybe force password change
        user = await prisma.user.update({
          where: { id: user.id },
          data: {
            emailVerified: true,
            ...(validatedData.adminPassword ? { mustChangePassword: true } : {}),
          },
        })
      }

      await prisma.userRole.upsert({
        where: {
          orgId_userId: {
            orgId: org.id,
            userId: user.id,
          },
        },
        update: { role: 'admin' },
        create: {
          orgId: org.id,
          userId: user.id,
          role: 'admin',
        },
      })

      if (validatedData.adminPassword) {
        await setCredentialPassword(user.id, validatedData.adminPassword)
        try {
          await sendAdminCredentialsEmail({
            to: validatedData.adminEmail,
            adminName: user.name || validatedData.adminEmail.split('@')[0],
            orgName: org.name,
            password: validatedData.adminPassword,
            loginUrl: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3010',
          })
        } catch (emailError) {
          console.error('E-Mail konnte nicht gesendet werden:', emailError)
        }
      }
    }

    revalidatePath('/superadmin')
    return { success: true, error: '' }
  } catch (error) {
    if (error instanceof z.ZodError) {
      return { success: false, error: error.errors[0].message }
    }
    return { success: false, error: 'Ein unerwarteter Fehler ist aufgetreten.' }
  }
}

export async function updateOrganization(id: string, prevState: any, formData: FormData) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  try {
    const rawData = {
      name: (formData.get('name') as string).trim(),
      plan: formData.get('plan') as string,
      contactEmail: (formData.get('contactEmail') as string).trim(),
      logoUrl: formData.get('logoUrl') as string,
      primaryColor: formData.get('primaryColor') as string,
      secondaryColor: formData.get('secondaryColor') as string,
      landingPageTitle: (formData.get('landingPageTitle') as string).trim(),
      landingPageText: (formData.get('landingPageText') as string).trim(),
      landingPageHeroImage: formData.get('landingPageHeroImage') as string,
      landingPageFeatures: (formData.get('landingPageFeatures') as string).trim(),
      landingPageFooter: (formData.get('landingPageFooter') as string).trim(),
      landingPageSectionTitle: (formData.get('landingPageSectionTitle') as string || '').trim(),
      landingPageButtonText: (formData.get('landingPageButtonText') as string || '').trim(),
      appStoreUrl: (formData.get('appStoreUrl') as string || '').trim(),
      playStoreUrl: (formData.get('playStoreUrl') as string || '').trim(),
    }

    const validatedData = updateOrgSchema.parse(rawData)

    await prisma.organization.update({
      where: { id },
      data: {
        name: validatedData.name,
        plan: validatedData.plan,
        contactEmail: validatedData.contactEmail || null,
        logoUrl: validatedData.logoUrl || null,
        primaryColor: validatedData.primaryColor || '#E63946',
        secondaryColor: validatedData.secondaryColor || null,
        landingPageTitle: validatedData.landingPageTitle || null,
        landingPageText: validatedData.landingPageText || null,
        landingPageHeroImage: validatedData.landingPageHeroImage || null,
        landingPageFeatures: toJsonbText(validatedData.landingPageFeatures),
        landingPageFooter: toJsonbText(validatedData.landingPageFooter),
        landingPageSectionTitle: validatedData.landingPageSectionTitle || null,
        landingPageButtonText: validatedData.landingPageButtonText || null,
        appStoreUrl: validatedData.appStoreUrl || null,
        playStoreUrl: validatedData.playStoreUrl || null,
      },
    })

    revalidatePath('/superadmin')
    revalidatePath(`/superadmin/organizations/${id}`)
    return { success: true, error: '' }
  } catch (error) {
    if (error instanceof z.ZodError) {
      return { success: false, error: error.errors[0].message }
    }
    return { success: false, error: 'Ein unerwarteter Fehler ist aufgetreten.' }
  }
}

export async function toggleAiFeature(id: string, enabled: boolean) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  await prisma.organization.update({
    where: { id },
    data: { aiEnabled: enabled },
  })

  revalidatePath('/superadmin')
  revalidatePath(`/superadmin/organizations/${id}`)
  return { success: true, error: '' }
}

export async function deleteOrganization(id: string) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  await prisma.organization.delete({ where: { id } })
  revalidatePath('/superadmin')
  redirect('/superadmin')
}

export async function createAdmin(prevState: any, formData: FormData) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  try {
    const rawData = {
      orgId: formData.get('orgId') as string,
      name: (formData.get('name') as string).trim(),
      email: normalizeEmail(formData.get('email') as string),
      password: formData.get('password') as string,
    }

    const validatedData = createAdminSchema.parse(rawData)

    let user = await prisma.user.findUnique({ where: { email: validatedData.email } })

    if (!user) {
      user = await prisma.user.create({
        data: {
          id: crypto.randomUUID(),
          name: validatedData.name,
          email: validatedData.email,
          emailVerified: true,
          mustChangePassword: true,
        },
      })
    } else {
      user = await prisma.user.update({
        where: { id: user.id },
        data: {
          emailVerified: true,
          mustChangePassword: true,
        },
      })
    }

    await setCredentialPassword(user.id, validatedData.password)

    await prisma.userRole.upsert({
      where: {
        orgId_userId: {
          orgId: validatedData.orgId,
          userId: user.id,
        },
      },
      update: { role: 'admin' },
      create: {
        orgId: validatedData.orgId,
        userId: user.id,
        role: 'admin',
      },
    })

    const org = await prisma.organization.findUnique({
      where: { id: validatedData.orgId },
      select: { name: true },
    })

    try {
      await sendAdminCredentialsEmail({
        to: validatedData.email,
        adminName: validatedData.name,
        orgName: org?.name || 'Ihre Innung',
        password: validatedData.password,
        loginUrl: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3010',
      })
    } catch (emailError) {
      console.error('E-Mail konnte nicht gesendet werden (Admin wurde trotzdem angelegt):', emailError)
    }

    revalidatePath(`/superadmin/organizations/${validatedData.orgId}`)
    return { success: true, error: '' }
  } catch (error) {
    console.error('Failed to create admin:', error)
    if (error instanceof z.ZodError) {
      return { success: false, error: error.errors[0].message }
    }
    return { success: false, error: 'Ein Fehler ist aufgetreten.' }
  }
}

export async function removeUserRole(id: string, orgId: string) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  await prisma.userRole.delete({ where: { id } })
  revalidatePath(`/superadmin/organizations/${orgId}`)
  return { success: true, error: '' }
}

export async function updateUserRole(id: string, orgId: string, role: string) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  await prisma.userRole.update({
    where: { id },
    data: { role },
  })
  revalidatePath(`/superadmin/organizations/${orgId}`)
  return { success: true, error: '' }
}

export async function removeMember(id: string, orgId: string) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  await prisma.member.delete({ where: { id } })
  revalidatePath(`/superadmin/organizations/${orgId}`)
  return { success: true, error: '' }
}

export async function createMember(prevState: any, formData: FormData) {
  const session = await requireSuperAdmin()
  if (!session) return { success: false, error: 'Nicht autorisiert.' }

  try {
    const rawData = {
      orgId: formData.get('orgId') as string,
      name: (formData.get('name') as string).trim(),
      email: normalizeEmail(formData.get('email') as string),
      betrieb: (formData.get('betrieb') as string).trim(),
      sparte: (formData.get('sparte') as string).trim(),
      ort: (formData.get('ort') as string).trim(),
    }

    const validatedData = createMemberSchema.parse(rawData)

    await prisma.member.create({
      data: {
        orgId: validatedData.orgId,
        name: validatedData.name,
        email: validatedData.email,
        betrieb: validatedData.betrieb,
        sparte: validatedData.sparte,
        ort: validatedData.ort,
        status: 'aktiv',
      },
    })

    revalidatePath(`/superadmin/organizations/${validatedData.orgId}`)
    return { success: true, error: '' }
  } catch (error) {
    console.error('Failed to create member:', error)
    if (error instanceof z.ZodError) {
      return { success: false, error: error.errors[0].message }
    }
    return { success: false, error: 'Ein Fehler ist aufgetreten.' }
  }
}
