import { EmailAddress, UniqueID } from "@/core/common/domain";
import {
  type ISequelizeMapper,
  type MapperParamsType,
  SequelizeMapper,
} from "@/core/common/infrastructure/sequelize/sequelize-mapper";
import { Result } from "@repo/rdx-utils";
import { User, Username } from "../../domain";
import { UserCreationAttributes, UserModel } from "../sequelize";

export interface IUserMapper extends ISequelizeMapper<UserModel, UserCreationAttributes, User> {}

class UserMapper
  extends SequelizeMapper<UserModel, UserCreationAttributes, User>
  implements IUserMapper
{
  public mapToDomain(source: UserModel, params?: MapperParamsType): Result<User, Error> {
    // Crear Value Objects asegurando que sean válidos
    const uniqueIdResult = UniqueID.create(source.id);
    const usernameResult = Username.create(source.username);
    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, emailResult]);
    if (okOrError.isFailure) {
      return Result.fail(okOrError.error.message);
    }

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

  public mapToPersistence(source: User, params?: MapperParamsType): UserCreationAttributes {
    return {
      id: source.id.toString(),
      username: source.username.toString(),
      email: source.email.toString(),
      //roles: source.getRoles().map((role) => role.toString()),
    };
  }
}

const userMapper: IUserMapper = new UserMapper();
export { userMapper };
