import * as Yup from "yup";

const REQUIRED = "Required.";
const USERNAME = Yup.string()
  .required(REQUIRED)
  .min(1, "Username is too short.");
const DISPLAY_NAME = Yup.string()
  .required(REQUIRED)
  .min(1, "Display name is too short.");
const EMAIL = Yup.string().required(REQUIRED).email("Not an email.");

const PASSWORD = Yup.string()
  .required(REQUIRED)
  .min(12, "Password must be at least 12 characters long.");
const CONFIRM_PASSWORD = (name: string) =>
  Yup.string()
    .required(REQUIRED)
    .oneOf([Yup.ref(name, {})], "Passwords must match.");

const AVATAR = Yup.string().test(
  "file-size",
  "File is bigger than 2 MB.",
  (value) => {
    if (value == null) return true;

    try {
      const buf = Buffer.from(value, "base64");
      return buf.length <= 2_000_000;
    } catch (e) {
      return false;
    }
  }
);

export const loginSchema = Yup.object().shape({
  username: USERNAME,
  password: PASSWORD
});

export type LoginFormValues = {
  username: string;
  password: string;
};

export const registerSchema: Yup.Schema<RegisterFormValues> =
  Yup.object().shape({
    username: USERNAME,
    displayName: DISPLAY_NAME,
    email: EMAIL,
    password: PASSWORD,
    confirmPassword: CONFIRM_PASSWORD("password"),
    avatar: AVATAR
  });

export interface RegisterFormValues {
  username: string;
  displayName: string;
  email: string;
  password: string;
  confirmPassword: string;
  avatar?: string;
}

export const aboutMeSchema: Yup.Schema<AboutMeFormValues> = Yup.object().shape({
  username: USERNAME,
  displayName: DISPLAY_NAME,
  email: EMAIL,
  avatar: AVATAR
});

export interface AboutMeFormValues {
  username: string;
  displayName: string;
  email: string;
  avatar?: string;
}

export const passwordUpdateSchema: Yup.Schema<PasswordUpdateFormValues> =
  Yup.object().shape({
    password: PASSWORD,
    newPassword: PASSWORD,
    confirmPassword: CONFIRM_PASSWORD("newPassword")
  });

export interface PasswordUpdateFormValues {
  password: string;
  newPassword: string;
  confirmPassword: string;
}

// Types specific to the server, because sometimes we omit fields (like confirmPassword)
export const registerServerSchema: Yup.Schema<RegisterServerFormValues> =
  Yup.object().shape({
    username: USERNAME,
    displayName: DISPLAY_NAME,
    email: EMAIL,
    password: PASSWORD,
    avatar: AVATAR
  });

export interface RegisterServerFormValues {
  username: string;
  displayName: string;
  email: string;
  password: string;
  avatar?: string;
}
