import {
  IsEmail,
  IsNotEmpty,
  MinLength,
  IsString,
  Matches,
  IsOptional,
  IsArray,
  IsNumber,
} from 'class-validator';
import {JSONSchema} from 'class-validator-jsonschema';

class SignUpBody {
  @JSONSchema({
    title: 'Email Address',
    description: 'Email address of the user, used as login identifier',
    example: 'user@example.com',
    type: 'string',
    format: 'email',
  })
  @IsEmail(undefined, {
    message: 'Invalid email address',
  })
  email: string;

  @JSONSchema({
    title: 'Password',
    description:
      'Password for account authentication (minimum 8 characters). Must contain: <br />\
1. **Uppercase letters** (A–Z)  <br /> \
2. **Lowercase letters** (a–z)  <br /> \
3. **Numbers** (0–9)   <br />\
4. **Special symbols** (`! @ # $ % ^ & * ( ) – _ = + [ ] { } | ; : , . ? /`) ',
    example: 'SecureP@ssw0rd',
    type: 'string',
    minLength: 8,
    writeOnly: true,
  })
  @IsNotEmpty()
  @MinLength(8)
  password: string;

  @JSONSchema({
    title: 'First Name',
    description: "User's first name (alphabetic characters only)",
    example: 'John',
    type: 'string',
  })
  @Matches(/^[A-Za-z ]+$/, {
    message: 'name can only contain alphabetic characters and spaces',
  })
  firstName: string;

  @JSONSchema({
    title: 'Last Name',
    description: "User's last name (alphabetic characters only)",
    example: 'Smith',
    type: 'string',
  })
  @Matches(/^[A-Za-z ]+$/, {
    message: 'name can only contain alphabetic characters and spaces',
  })
  @IsOptional()
  lastName?: string;

  @JSONSchema({
    title: 'reCAPTCHA Token',
    description: 'reCAPTCHA verification token obtained from the frontend widget',
    example: '03AGdBq27...',
    type: 'string',
  })
  @IsString()
  @IsNotEmpty()
  recaptchaToken: string;

  @JSONSchema({
    title: 'Profile Image',
    description: 'Optional student profile image as a data URL or remote URL',
    example: 'data:image/jpeg;base64,/9j/4AAQSk...',
    type: 'string',
  })
  @IsOptional()
  @IsString()
  profileImage?: string;

  @JSONSchema({
    title: 'Face Embedding',
    description: 'Optional 128-length face embedding generated from the registration image',
    type: 'array',
    items: {
      type: 'number',
    },
  })
  @IsOptional()
  @IsArray()
  @IsNumber({}, {each: true})
  faceEmbedding?: number[];
}

class GoogleSignUpBody {
  @JSONSchema({
    title: 'Email Address',
    description: 'Email address of the user, used as login identifier',
    example: 'user@example.com',
    type: 'string',
    format: 'email',
  })
  @IsEmail(undefined, {
    message: 'Invalid email address',
  })
  email: string;

  @JSONSchema({
    title: 'First Name',
    description: "User's first name (alphabetic characters only)",
    example: 'John',
    type: 'string',
  })
  @Matches(/^[A-Za-z ]+$/, {
    message: 'name can only contain alphabetic characters and spaces',
  })
  firstName: string;

  @JSONSchema({
    title: 'Last Name',
    description: "User's last name (alphabetic characters only)",
    example: 'Smith',
    type: 'string',
  })
  @Matches(/^[A-Za-z ]+$/, {
    message: 'name can only contain alphabetic characters and spaces',
  })
  @IsOptional()
  lastName?: string;

  @JSONSchema({
    title: 'Role',
    description: 'Selected role at signup time. Students must also provide profileImage and faceEmbedding for proctoring.',
    example: 'student',
    type: 'string',
  })
  @IsOptional()
  @IsString()
  role?: string;

  @JSONSchema({
    title: 'Profile Image',
    description: 'Student profile image as a data URL or remote URL. Required for student role.',
    example: 'data:image/jpeg;base64,/9j/4AAQSk...',
    type: 'string',
  })
  @IsOptional()
  @IsString()
  profileImage?: string;

  @JSONSchema({
    title: 'Face Embedding',
    description: '128-length face embedding generated from the registration image. Required for student role.',
    type: 'array',
    items: {
      type: 'number',
    },
  })
  @IsOptional()
  @IsArray()
  @IsNumber({}, {each: true})
  faceEmbedding?: number[];
}

class VerifySignUpProviderBody {
  @JSONSchema({
    title: 'Firebase Auth Token',
    description: 'Firebase Auth Token',
    example: '43jdlsaksla;f328e9fjhsda',
    type: 'string',
  })
  @IsString()
  token: string;
}

class ChangePasswordBody {
  @IsString()
  @IsNotEmpty()
  @MinLength(8)
  @Matches(/^[A-Za-z ]+$/, {
    message: 'Password Invalid',
  })
  @JSONSchema({
    title: 'New Password',
    description:
      'New password that meets security requirements.  Must contain: <br />\
1. **Uppercase letters** (A–Z)  <br /> \
2. **Lowercase letters** (a–z)  <br /> \
3. **Numbers** (0–9)   <br />\
4. **Special symbols** (`! @ # $ % ^ & * ( ) – _ = + [ ] { } | ; : , . ? /`) ',
    example: 'SecureP@ssw0rd',
    type: 'string',
    minLength: 8,
    writeOnly: true,
  })
  newPassword: string;

  @IsString()
  @IsNotEmpty()
  @MinLength(8)
  @Matches(/^[A-Za-z ]+$/, {
    message: 'Password Invalid',
  })
  @JSONSchema({
    title: 'Confirm New Password',
    description:
      'Confirmation of the new password (must match exactly). Must contain: <br />\
1. **Uppercase letters** (A–Z)  <br /> \
2. **Lowercase letters** (a–z)  <br /> \
3. **Numbers** (0–9)   <br />\
4. **Special symbols** (`! @ # $ % ^ & * ( ) – _ = + [ ] { } | ; : , . ? /`) ',
    example: 'SecureP@ssw0rd',
    type: 'string',
    minLength: 8,
    writeOnly: true,
  })
  newPasswordConfirm: string;
}

class SignUpResponse {
  @JSONSchema({
    description: 'Unique identifier for the user',
    example: 'cKy6H2O04PgTh8O3DpUXjgJYUr53',
    type: 'string',
    readOnly: true,
  })
  @IsNotEmpty()
  @IsString()
  uid: string;

  @JSONSchema({
    description: 'Email address of the registered user',
    example: 'user@example.com',
    type: 'string',
    format: 'email',
    readOnly: true,
  })
  @IsEmail()
  email: string;

  @JSONSchema({
    description: "User's first name",
    example: 'John',
    type: 'string',
    readOnly: true,
  })
  @IsString()
  firstName: string;

  @JSONSchema({
    description: "User's last name",
    example: 'Smith',
    type: 'string',
    readOnly: true,
  })
  @IsString()
  lastName: string;
}

class ChangePasswordResponse {
  @JSONSchema({
    description: 'Indicates the operation was successful',
    example: true,
    type: 'boolean',
    readOnly: true,
  })
  @IsNotEmpty()
  success: boolean;

  @JSONSchema({
    description: 'Success message',
    example: 'Password changed successfully',
    type: 'string',
    readOnly: true,
  })
  @IsString()
  message: string;
}

class TokenVerificationResponse {
  @JSONSchema({
    description: 'Confirmation message for valid token',
    example: 'Token is valid',
    type: 'string',
    readOnly: true,
  })
  @IsString()
  message: string;
}

class AuthErrorResponse {
  @JSONSchema({
    description: 'The error message',
    example: 'Invalid credentials. Please check your email and password.',
    type: 'string',
    readOnly: true,
  })
  @IsNotEmpty()
  @IsString()
  message: string;
}

class LoginBody {
  @JSONSchema({
    title: 'Email Address',
    description: 'Email address of the user',
    format: 'email',
  })
  @IsEmail()
  email: string;

  @JSONSchema({
    title: 'Password',
    description: 'Password for account authentication',
    example: 'SecureP@ssw0rd',
    minLength: 8,
    writeOnly: true,
  })
  @IsNotEmpty()
  @MinLength(8)
  password: string;

  @JSONSchema({
    title: 'reCAPTCHA Token',
    description: 'reCAPTCHA verification token obtained from the frontend widget',
    example: '03AGdBq27...',
    type: 'string',
  })
  @IsString()
  @IsNotEmpty()
  recaptchaToken: string;
}

class LoginResponse {
  @JSONSchema({
    description: 'Local ID of the user',
    example: 'cKy6H2O04PgTh8O3DpUXjgJYUr53',
    type: 'string',
  })
  @IsString()
  localId: string;

  @JSONSchema({
    description: 'Email address of the user',
    example: 'user@example.com',
    type: 'string',
    format: 'email',
  })
  @IsString()
  email: string;

  @JSONSchema({
    description: 'Display name of the user',
    example: 'John Doe',
    type: 'string',
  })
  @IsString()
  displayName: string;

  @JSONSchema({
    description: 'ID token of the user',
    example: 'cKy6H2O04PgTh8O3DpUXjgJYUr53',
    type: 'string',
  })
  @IsString()
  idToken: string;

  @JSONSchema({
    description: 'Refresh token of the user',
    example: 'cKy6H2O04PgTh8O3DpUXjgJYUr53',
    type: 'string',
  })
  @IsString()
  refreshToken: string;

  @JSONSchema({
    description: 'Expiry time of the ID token',
    example: '3600',
    type: 'number',
  })
  expiresIn: Number;
}

export const AUTH_VALIDATORS = [
  SignUpBody,
  GoogleSignUpBody,
  ChangePasswordBody,
  SignUpResponse,
  VerifySignUpProviderBody,
  ChangePasswordResponse,
  TokenVerificationResponse,
  AuthErrorResponse,
  LoginBody,
  LoginResponse,
];

export {
  SignUpBody,
  GoogleSignUpBody,
  ChangePasswordBody,
  SignUpResponse,
  VerifySignUpProviderBody,
  ChangePasswordResponse,
  TokenVerificationResponse,
  AuthErrorResponse,
  LoginBody,
  LoginResponse,
};
