import "server-only";

import { AuditTargetType, InvitationStatus, UserRole } from "@prisma/client";

import { prisma } from "@/lib/prisma";

const roleOrder: UserRole[] = [
  UserRole.ADMIN,
  UserRole.KOORDINATOR,
  UserRole.ERZIEHER,
  UserRole.ELTERN,
];

export type KitaOverviewRow = {
  id: string;
  name: string;
  slug: string;
  createdAt: Date;
  updatedAt: Date;
  modules: {
    notdienst: boolean;
    termine: boolean;
    adressbuch: boolean;
  };
  counts: {
    users: number;
    families: number;
    activeChildren: number;
    termine: number;
    absences: number;
    announcements: number;
    openInvitations: number;
    lockedUsers: number;
    missingConsent: number;
    familiesWithoutUsers: number;
  };
  lastLoginAt: Date | null;
  roleCounts: Record<UserRole, number>;
};

export type GlobalAdminHealth = {
  orphanTenantUsers: number;
  lockedTenantUsers: number;
  openInvitations: number;
  missingConsent: number;
  kitas: number;
};

export async function getGlobalAdminHealth(): Promise<GlobalAdminHealth> {
  const now = new Date();
  const [
    orphanTenantUsers,
    lockedTenantUsers,
    openInvitations,
    missingConsent,
    kitas,
  ] = await Promise.all([
    prisma.user.count({
      where: {
        kitaId: null,
        role: { not: UserRole.SUPERADMIN },
      },
    }),
    prisma.user.count({
      where: {
        role: { not: UserRole.SUPERADMIN },
        lockedUntil: { gt: now },
      },
    }),
    prisma.invitation.count({
      where: {
        status: InvitationStatus.PENDING,
        expiresAt: { gt: now },
      },
    }),
    prisma.user.count({
      where: {
        role: { not: UserRole.SUPERADMIN },
        privacyPolicyAcceptedAt: null,
      },
    }),
    prisma.kita.count(),
  ]);

  return {
    orphanTenantUsers,
    lockedTenantUsers,
    openInvitations,
    missingConsent,
    kitas,
  };
}

export async function getKitaOverviewRows(): Promise<KitaOverviewRow[]> {
  const now = new Date();
  const kitas = await prisma.kita.findMany({
    select: {
      id: true,
      name: true,
      slug: true,
      notdienstModuleEnabled: true,
      terminModuleEnabled: true,
      adressbuchModuleEnabled: true,
      createdAt: true,
      updatedAt: true,
      users: {
        select: {
          role: true,
          lastLoginAt: true,
          lockedUntil: true,
          privacyPolicyAcceptedAt: true,
        },
      },
      families: {
        select: {
          users: {
            select: { id: true },
          },
        },
      },
      children: {
        select: { active: true },
      },
      invitations: {
        select: {
          status: true,
          expiresAt: true,
        },
      },
      _count: {
        select: {
          termine: true,
          absences: true,
          announcements: true,
        },
      },
    },
    orderBy: { name: "asc" },
  });

  return kitas.map((kita) => {
    const roleCounts = Object.fromEntries(
      Object.values(UserRole).map((role) => [role, 0]),
    ) as Record<UserRole, number>;

    let lastLoginAt: Date | null = null;
    let lockedUsers = 0;
    let missingConsent = 0;

    for (const user of kita.users) {
      roleCounts[user.role] += 1;
      if (user.lastLoginAt && (!lastLoginAt || user.lastLoginAt > lastLoginAt)) {
        lastLoginAt = user.lastLoginAt;
      }
      if (user.lockedUntil && user.lockedUntil > now) {
        lockedUsers += 1;
      }
      if (user.role !== UserRole.SUPERADMIN && !user.privacyPolicyAcceptedAt) {
        missingConsent += 1;
      }
    }

    return {
      id: kita.id,
      name: kita.name,
      slug: kita.slug,
      createdAt: kita.createdAt,
      updatedAt: kita.updatedAt,
      modules: {
        notdienst: kita.notdienstModuleEnabled,
        termine: kita.terminModuleEnabled,
        adressbuch: kita.adressbuchModuleEnabled,
      },
      counts: {
        users: kita.users.length,
        families: kita.families.length,
        activeChildren: kita.children.filter((child) => child.active).length,
        termine: kita._count.termine,
        absences: kita._count.absences,
        announcements: kita._count.announcements,
        openInvitations: kita.invitations.filter(
          (invitation) =>
            invitation.status === InvitationStatus.PENDING &&
            invitation.expiresAt > now,
        ).length,
        lockedUsers,
        missingConsent,
        familiesWithoutUsers: kita.families.filter(
          (family) => family.users.length === 0,
        ).length,
      },
      lastLoginAt,
      roleCounts,
    };
  });
}

export type KitaDiagnostics = {
  kita: {
    id: string;
    name: string;
    slug: string;
    createdAt: Date;
    updatedAt: Date;
    modules: KitaOverviewRow["modules"];
  };
  counts: KitaOverviewRow["counts"] & {
    inactiveChildren: number;
    expiredPendingInvitations: number;
  };
  roleCounts: Record<UserRole, number>;
  users: {
    id: string;
    email: string;
    firstName: string;
    lastName: string;
    role: UserRole;
    familyName: string | null;
    emailVerifiedAt: Date | null;
    privacyPolicyAcceptedAt: Date | null;
    lastLoginAt: Date | null;
    failedLoginAttempts: number;
    lockedUntil: Date | null;
    createdAt: Date;
  }[];
  diagnostics: {
    lockedUsers: number;
    missingConsent: number;
    unverifiedUsers: number;
    familiesWithoutUsers: number;
    usersWithEmptyPassword: number;
  };
};

export async function getKitaDiagnostics(
  kitaId: string,
): Promise<KitaDiagnostics | null> {
  const now = new Date();
  const kita = await prisma.kita.findUnique({
    where: { id: kitaId },
    select: {
      id: true,
      name: true,
      slug: true,
      notdienstModuleEnabled: true,
      terminModuleEnabled: true,
      adressbuchModuleEnabled: true,
      createdAt: true,
      updatedAt: true,
      users: {
        select: {
          id: true,
          email: true,
          firstName: true,
          lastName: true,
          role: true,
          passwordHash: true,
          emailVerifiedAt: true,
          privacyPolicyAcceptedAt: true,
          lastLoginAt: true,
          failedLoginAttempts: true,
          lockedUntil: true,
          createdAt: true,
          family: {
            select: { name: true },
          },
        },
        orderBy: [
          { role: "asc" },
          { lastName: "asc" },
          { firstName: "asc" },
        ],
      },
      families: {
        select: {
          users: { select: { id: true } },
        },
      },
      children: {
        select: { active: true },
      },
      invitations: {
        select: {
          status: true,
          expiresAt: true,
        },
      },
      _count: {
        select: {
          termine: true,
          absences: true,
          announcements: true,
        },
      },
    },
  });

  if (!kita) {
    return null;
  }

  const roleCounts = Object.fromEntries(
    Object.values(UserRole).map((role) => [role, 0]),
  ) as Record<UserRole, number>;

  let lockedUsers = 0;
  let missingConsent = 0;
  let unverifiedUsers = 0;
  let usersWithEmptyPassword = 0;

  for (const user of kita.users) {
    roleCounts[user.role] += 1;
    if (user.lockedUntil && user.lockedUntil > now) {
      lockedUsers += 1;
    }
    if (user.role !== UserRole.SUPERADMIN && !user.privacyPolicyAcceptedAt) {
      missingConsent += 1;
    }
    if (!user.emailVerifiedAt) {
      unverifiedUsers += 1;
    }
    if (!user.passwordHash) {
      usersWithEmptyPassword += 1;
    }
  }

  const activeChildren = kita.children.filter((child) => child.active).length;
  const inactiveChildren = kita.children.length - activeChildren;
  const familiesWithoutUsers = kita.families.filter(
    (family) => family.users.length === 0,
  ).length;

  return {
    kita: {
      id: kita.id,
      name: kita.name,
      slug: kita.slug,
      createdAt: kita.createdAt,
      updatedAt: kita.updatedAt,
      modules: {
        notdienst: kita.notdienstModuleEnabled,
        termine: kita.terminModuleEnabled,
        adressbuch: kita.adressbuchModuleEnabled,
      },
    },
    counts: {
      users: kita.users.length,
      families: kita.families.length,
      activeChildren,
      inactiveChildren,
      termine: kita._count.termine,
      absences: kita._count.absences,
      announcements: kita._count.announcements,
      openInvitations: kita.invitations.filter(
        (invitation) =>
          invitation.status === InvitationStatus.PENDING &&
          invitation.expiresAt > now,
      ).length,
      expiredPendingInvitations: kita.invitations.filter(
        (invitation) =>
          invitation.status === InvitationStatus.PENDING &&
          invitation.expiresAt <= now,
      ).length,
      lockedUsers,
      missingConsent,
      familiesWithoutUsers,
    },
    roleCounts,
    users: kita.users.map((user) => ({
      id: user.id,
      email: user.email,
      firstName: user.firstName,
      lastName: user.lastName,
      role: user.role,
      familyName: user.family?.name ?? null,
      emailVerifiedAt: user.emailVerifiedAt,
      privacyPolicyAcceptedAt: user.privacyPolicyAcceptedAt,
      lastLoginAt: user.lastLoginAt,
      failedLoginAttempts: user.failedLoginAttempts,
      lockedUntil: user.lockedUntil,
      createdAt: user.createdAt,
    })),
    diagnostics: {
      lockedUsers,
      missingConsent,
      unverifiedUsers,
      familiesWithoutUsers,
      usersWithEmptyPassword,
    },
  };
}

export async function recordKitaDiagnosticView({
  actorUserId,
  actorEmail,
  kitaId,
  kitaName,
  kitaSlug,
}: {
  actorUserId: string;
  actorEmail: string;
  kitaId: string;
  kitaName: string;
  kitaSlug: string;
}) {
  await prisma.auditLog.create({
    data: {
      actorUserId,
      actorEmail,
      action: "KITA_DIAGNOSTIC_VIEW",
      targetType: AuditTargetType.KITA,
      targetId: kitaId,
      targetLabel: `${kitaName} (${kitaSlug})`,
      targetKitaId: kitaId,
    },
  });
}

export async function getAuditLogRows() {
  return prisma.auditLog.findMany({
    select: {
      id: true,
      actorEmail: true,
      action: true,
      targetType: true,
      targetId: true,
      targetLabel: true,
      targetKitaId: true,
      metadata: true,
      createdAt: true,
    },
    orderBy: { createdAt: "desc" },
    take: 200,
  });
}

export { roleOrder };

