import {
  EmailAddress,
  ISequelizeMapper,
  MapperParamsType,
  Result,
  SequelizeMapper,
  UniqueID,
} from "@/core";
import { AuthUserCreationAttributes, AuthUserModel } from '../sequelize';
import { AuthenticatedUser, HashPassword, Username } from '../../domain';

export interface IAuthenticatedUserMapper
  extends ISequelizeMapper<AuthUserModel, AuthUserCreationAttributes, AuthenticatedUser> {}

export class AuthenticatedUserMapper
  extends SequelizeMapper<AuthUserModel, AuthUserCreationAttributes, AuthenticatedUser>
  implements IAuthenticatedUserMapper
{
  public mapToDomain(
    source: AuthUserModel,
    params?: MapperParamsType
  ): Result<AuthenticatedUser, Error> {
    // Crear Value Objects asegurando que sean válidos
    const uniqueIdResult = UniqueID.create(source.id);
    const usernameResult = Username.create(source.username);
    const passwordHashResult = HashPassword.createFromHash(source.hash_password);
    const emailResult = EmailAddress.create(source.email);

    // Validar que no haya errores en la creación de los Value Objects
    const okOrError = Result.combine([
      uniqueIdResult,
      usernameResult,
      passwordHashResult,
      emailResult,
    ]);
    if (okOrError.isFailure) {
      return Result.fail(okOrError.error.message);
    }

    // Crear el agregado de dominio
    return AuthenticatedUser.create(
      {
        username: usernameResult.data!,
        email: emailResult.data!,
        hashPassword: passwordHashResult.data!,
        roles: source.roles || [],
      },
      uniqueIdResult.data!
    );
  }

  public mapToPersistence(
    source: AuthenticatedUser,
    params?: MapperParamsType
  ): AuthUserCreationAttributes {
    return {
      id: source.id.toString(),
      username: source.username.toString(),
      email: source.email.toString(),
      hash_password: source.hashPassword.toString(),
      roles: source.getRoles().map((role) => role.toString()),
      //access_token: source.accessToken,
      //refresh_token: source.refreshToken,
    };
  }
}

const authenticatedUserMapper: IAuthenticatedUserMapper = new AuthenticatedUserMapper();
export { authenticatedUserMapper };
