import { z } from "zod";

export const ZUserLocale = z.enum([
  "de-DE",
  "en-US",
  "es-ES",
  "fr-FR",
  "hu-HU",
  "ja-JP",
  "nl-NL",
  "pt-BR",
  "pt-PT",
  "ro-RO",
  "ru-RU",
  "sv-SE",
  "zh-Hans-CN",
  "zh-Hant-TW",
]);

export type TUserLocale = z.infer<typeof ZUserLocale>;

export const ZUserNotificationSettings = z.object({
  alert: z.record(z.string(), z.boolean()),
  unsubscribedOrganizationIds: z.array(z.string()).optional(),
});

export const ZUserName = z
  .string()
  .trim()
  .min(1, {
    error: "Name should be at least 1 character long",
  })
  .regex(/^[\p{L}\p{M}\s'\d-]+$/u, "Invalid name format");

export const ZUserEmail = z
  .email({
    error: "Invalid email",
  })
  .max(255);

export type TUserEmail = z.infer<typeof ZUserEmail>;

export const ZUserPassword = z
  .string()
  .min(8, {
    error: "Password must be at least 8 characters long",
  })
  .max(128, {
    error: "Password must be 128 characters or less",
  })
  .regex(/^(?=.*[A-Z])(?=.*\d).*$/);

export type TUserPassword = z.infer<typeof ZUserPassword>;

export type TUserNotificationSettings = z.infer<typeof ZUserNotificationSettings>;

const ZUserIdentityProvider = z.enum(["email", "google", "github", "azuread", "openid", "saml"]);

export const ZUser = z.object({
  id: z.string(),
  name: ZUserName,
  email: ZUserEmail,
  emailVerified: z.date().nullable(),
  twoFactorEnabled: z.boolean(),
  identityProvider: ZUserIdentityProvider,
  createdAt: z.date(),
  updatedAt: z.date(),
  notificationSettings: ZUserNotificationSettings,
  locale: ZUserLocale,
  lastLoginAt: z.date().nullable(),
  isActive: z.boolean().prefault(true),
});

export type TUser = z.infer<typeof ZUser>;

export const ZUserUpdateInput = z.object({
  name: ZUserName.optional(),
  email: ZUserEmail.optional(),
  emailVerified: z.date().nullish(),
  password: ZUserPassword.optional(),
  notificationSettings: ZUserNotificationSettings.optional(),
  locale: ZUserLocale.optional(),
  lastLoginAt: z.date().nullish(),
  isActive: z.boolean().optional(),
});

export type TUserUpdateInput = z.infer<typeof ZUserUpdateInput>;

export const ZUserCreateInput = z.object({
  name: ZUserName,
  email: ZUserEmail,
  password: ZUserPassword.optional(),
  emailVerified: z.date().optional(),
  identityProvider: ZUserIdentityProvider.optional(),
  identityProviderAccountId: z.string().optional(),
  locale: ZUserLocale.optional(),
});

export type TUserCreateInput = z.infer<typeof ZUserCreateInput>;

export const ZUserPersonalInfoUpdateInput = ZUserUpdateInput.pick({
  name: true,
  email: true,
  locale: true,
}).extend({
  password: ZUserPassword.optional(),
});

export type TUserPersonalInfoUpdateInput = z.infer<typeof ZUserPersonalInfoUpdateInput>;
