import { z } from 'zod';
import { userRoleSchema } from '../role';
import { USER_TYPE } from './User.const';

export const userTypeSchema = z.enum(USER_TYPE);

export const PHONE_REGEX = /^([+]?[\\s0-9]+)?(\\d{3}|[(]?[0-9]+[)])?([-]?[\\s]?[0-9])+$/;
const MIN_PASSWORD_LENGTH = 6;

export const emailOrPhoneSchema = z
  .string()
  .min(1, 'Email or phone is required')
  .refine(
    (val) => {
      const isEmail = z.email().safeParse(val).success;
      const isPhone = PHONE_REGEX.test(val);
      return isEmail || isPhone;
    },
    { message: 'Must be a valid email or phone number' },
  );

const baseUserObj = z.object({
  id: z.uuidv4(),

  name: z.string(),
  lastName: z.string(),

  email: z.email().toLowerCase().optional().nullable(),

  phoneNumber: z.string().regex(PHONE_REGEX, 'Invalid phone number format').optional().nullable(),

  // --- ACCESS CONTROL ---
  role: userRoleSchema,
  type: userTypeSchema,

  isActive: z.boolean().default(true),
  // TODO: Implement mechanism to validate users later by email or phone
  isEmailVerified: z.boolean().default(false),
  isPhoneVerified: z.boolean().default(false),

  defaultPlayerId: z.uuidv4().optional(),

  createdAt: z.date(),
  lastLoginAt: z.date().optional(),
});

export const userSchema = baseUserObj.refine((data) => data.email || data.phoneNumber, {
  message: 'User must have either an email or a phone number',
  path: ['email', 'phoneNumber'],
});

/**
 * The schema for the user returned on login
 */
export const authUserSchema = baseUserObj.extend({
  authToken: z.string(),
});

export const userWithPasswordSchema = userSchema.and(
  z.object({
    password: z.string().min(MIN_PASSWORD_LENGTH),
  }),
);

export const userInitialRegistrationSchema = z.object({
  emailOrPhone: emailOrPhoneSchema,
  password: z.string().min(MIN_PASSWORD_LENGTH, `Password must be at least ${MIN_PASSWORD_LENGTH} characters`),
});

export const userVerifySchema = z.object({
  emailOrPhone: emailOrPhoneSchema,
  code: z.string().min(6, 'Code must be at least 6 characters').max(10, 'Code is too long'),
});

export const userCompleteProfileSchema = baseUserObj
  .pick({
    name: true,
  })
  .extend({
    lastName: z.string().optional(),
    nickname: z.string().min(2),
    birthDate: z.coerce.date(),
    waiverSignature: z.boolean().refine((val) => val === true, {
      message: 'You must accept the waiver signature',
    }),
    teamName: z.string().optional(),
  });

// Deprecated in favor of multi-step registration
export const userRegistrationInputSchema = baseUserObj
  .pick({
    name: true,
    lastName: true,
    email: true,
    phoneNumber: true,
  })
  .extend({
    password: z.string().min(6),
    nickname: z.string().min(2),
    birthDate: z.coerce.date(),
  })
  .refine((data) => data.email || data.phoneNumber, {
    message: 'User must have either an email or a phone number',
    path: ['email', 'phoneNumber'],
  });

export const userLoginInputSchema = z.object({
  emailOrPhone: emailOrPhoneSchema,
  password: z.string().min(MIN_PASSWORD_LENGTH, `Password must be at least ${MIN_PASSWORD_LENGTH} characters`),
});
