package de.effigenix.infrastructure.usermanagement.persistence.mapper;

import de.effigenix.domain.usermanagement.*;
import de.effigenix.infrastructure.usermanagement.persistence.entity.RoleEntity;
import de.effigenix.infrastructure.usermanagement.persistence.entity.UserEntity;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Maps between User domain entity and UserEntity JPA entity.
 * Infrastructure Layer - translates between Domain and Persistence layers.
 *
 * This is a crucial part of Hexagonal Architecture:
 * - Domain layer defines pure business logic (User)
 * - Infrastructure layer handles persistence (UserEntity)
 * - Mapper translates between the two layers
 */
@Component
public class UserMapper {

    private final RoleMapper roleMapper;

    public UserMapper(RoleMapper roleMapper) {
        this.roleMapper = roleMapper;
    }

    /**
     * Converts a User domain entity to a UserEntity JPA entity.
     * Used when saving to the database.
     */
    public UserEntity toEntity(User user) {
        if (user == null) {
            return null;
        }

        Set<RoleEntity> roleEntities = user.roles().stream()
                .map(roleMapper::toEntity)
                .collect(Collectors.toSet());

        return new UserEntity(
                user.id().value(),
                user.username(),
                user.email(),
                user.passwordHash().value(),
                roleEntities,
                user.branchId(),
                user.status(),
                user.createdAt(),
                user.lastLogin()
        );
    }

    /**
     * Converts a UserEntity JPA entity to a User domain entity.
     * Used when loading from the database.
     */
    public User toDomain(UserEntity entity) {
        if (entity == null) {
            return null;
        }

        Set<Role> roles = entity.getRoles() != null
                ? entity.getRoles().stream()
                        .map(roleMapper::toDomain)
                        .collect(Collectors.toSet())
                : new HashSet<>();

        return User.reconstitute(
                UserId.of(entity.getId()),
                entity.getUsername(),
                entity.getEmail(),
                PasswordHash.of(entity.getPasswordHash()),
                roles,
                entity.getBranchId(),
                entity.getStatus(),
                entity.getCreatedAt(),
                entity.getLastLogin()
        );
    }
}
