import { IsString, IsEmail, IsBoolean, IsOptional, IsArray, MinLength } from 'class-validator';

export class User {
  id?: string;
  username: string = '';
  email: string = '';
  firstName?: string = '';
  lastName?: string = '';
  enabled: boolean = true;
  emailVerified: boolean = false;
  attributes?: Record<string, any> = {};
  clientRoles: string[] = [];
  createdTimestamp?: number;

  constructor(partial?: Partial<User>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UserCredentials {
  type: string = 'password';
  value: string = '';
  temporary: boolean = false;

  constructor(type?: string, value?: string, temporary?: boolean) {
    if (type) this.type = type;
    if (value) this.value = value;
    if (temporary !== undefined) this.temporary = temporary;
  }
}

export class CreateUserDto {
  @IsString()
  @MinLength(3)
  username: string = '';

  @IsEmail()
  email: string = '';

  @IsOptional()
  @IsString()
  firstName: string = '';

  @IsOptional()
  @IsString()
  lastName: string = '';

  @IsString()
  @MinLength(8)
  password: string = '';

  @IsOptional()
  @IsBoolean()
  enabled: boolean = true;

  @IsOptional()
  @IsBoolean()
  emailVerified: boolean = false;

  @IsOptional()
  attributes?: Record<string, any> = {};

  @IsOptional()
  @IsArray()
  clientRoles: string[] = [];

  constructor(partial?: Partial<CreateUserDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UpdateUserDto {
  @IsOptional()
  @IsString()
  username?: string;

  @IsOptional()
  @IsEmail()
  email?: string;

  @IsOptional()
  @IsString()
  firstName?: string;

  @IsOptional()
  @IsString()
  lastName?: string;

  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @IsBoolean()
  emailVerified?: boolean;

  @IsOptional()
  attributes?: Record<string, any>;

  @IsOptional()
  @IsArray()
  clientRoles?: string[];

  constructor(partial?: Partial<UpdateUserDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UserQueryDto {
  @IsOptional()
  page: number = 1;

  @IsOptional()
  limit: number = 10;

  @IsOptional()
  @IsString()
  search?: string;

  @IsOptional()
  @IsBoolean()
  enabled?: boolean;

  @IsOptional()
  @IsBoolean()
  emailVerified?: boolean;

  @IsOptional()
  @IsString()
  email?: string;

  @IsOptional()
  @IsString()
  username?: string;

  @IsOptional()
  @IsString()
  firstName?: string;

  @IsOptional()
  @IsString()
  lastName?: string;

  constructor(partial?: Partial<UserQueryDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class ResetPasswordDto {
  @IsString()
  userId: string = '';

  @IsString()
  @MinLength(8)
  newPassword: string = '';

  @IsOptional()
  @IsBoolean()
  temporary: boolean = false;

  constructor(partial?: Partial<ResetPasswordDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UserResponse {
  id: string = '';
  username: string = '';
  email: string = '';
  firstName: string = '';
  lastName: string = '';
  enabled: boolean = true;
  emailVerified: boolean = false;
  attributes: Record<string, any> = {};
  clientRoles: string[] = [];
  createdTimestamp: number = Date.now();

  constructor(user?: any) {
    if (user) {
      this.id = user.id || '';
      this.username = user.username || '';
      this.email = user.email || '';
      this.firstName = user.firstName || '';
      this.lastName = user.lastName || '';
      this.enabled = user.enabled ?? true;
      this.emailVerified = user.emailVerified ?? false;
      this.attributes = user.attributes || {};
      this.clientRoles = user.clientRoles || [];
      this.createdTimestamp = user.createdTimestamp || Date.now();
    }
  }
}

export class PaginatedUserResponse {
  users: UserResponse[] = [];
  total: number = 0;
  page: number = 1;
  limit: number = 10;
  totalPages: number = 0;

  constructor(users: UserResponse[] = [], total: number = 0, page: number = 1, limit: number = 10) {
    this.users = users;
    this.total = total;
    this.page = page;
    this.limit = limit;
    this.totalPages = Math.ceil(total / limit) || 0;
  }
}

export class AssignRolesDto {
  @IsArray()
  @IsString({ each: true })
  roles: string[] = [];

  constructor(partial?: Partial<AssignRolesDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class LoginDto {
  @IsString()
  username: string = '';

  @IsString()
  password: string = '';

  constructor(partial?: Partial<LoginDto>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class TokenResponse {
  access_token: string = '';
  refresh_token?: string = '';
  expires_in: number = 0;
  token_type: string = '';
  scope?: string = '';

  constructor(partial?: Partial<TokenResponse>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class ApiResponse<T> {
  data: T | null = null;
  message: string = '';
  status: string = '';

  constructor(partial?: Partial<ApiResponse<T>>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UserRoleMapping {
  id: string = '';
  name: string = '';
  description?: string = '';
  composite?: boolean = false;
  clientRole?: boolean = false;
  containerId?: string = '';

  constructor(partial?: Partial<UserRoleMapping>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

export class UserSession {
  id: string = '';
  username: string = '';
  userId: string = '';
  ipAddress: string = '';
  start: number = 0;
  lastAccess: number = 0;
  clients: Record<string, string> = {};

  constructor(partial?: Partial<UserSession>) {
    if (partial) {
      Object.assign(this, partial);
    }
  }
}

// Types pour les rôles client
export type ClientRole = 
  | 'dcb-admin' 
  | 'dcb-partner' 
  | 'dcb-support' 
  | 'dcb-partner-admin' 
  | 'dcb-partner-manager' 
  | 'dcb-partner-support' 
  | 'dcb-partner-user';