package com.qqchen.deploy.backend.framework.converter;

import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.springframework.data.domain.Page;

import java.util.List;
import java.util.stream.Collectors;

@org.mapstruct.MapperConfig(
    componentModel = "spring",
    unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE,
    uses = {EnumListConverter.class}
)
public interface BaseConverter<T extends Entity<?>, D extends BaseDTO> {

    @Mappings({
        @Mapping(target = "id", source = "id"),
        @Mapping(target = "createTime", source = "createTime"),
        @Mapping(target = "createBy", source = "createBy"),
        @Mapping(target = "updateTime", source = "updateTime"),
        @Mapping(target = "updateBy", source = "updateBy"),
        @Mapping(target = "version", source = "version"),
        @Mapping(target = "deleted", source = "deleted")
    })
    D toDto(T entity);

    @Mappings({
        @Mapping(target = "id", source = "id"),
        @Mapping(target = "createTime", source = "createTime"),
        @Mapping(target = "createBy", source = "createBy"),
        @Mapping(target = "updateTime", source = "updateTime"),
        @Mapping(target = "updateBy", source = "updateBy"),
        @Mapping(target = "version", source = "version"),
        @Mapping(target = "deleted", source = "deleted")
    })
    T toEntity(D dto);

    @Mappings({
        @Mapping(target = "id", ignore = true),
        @Mapping(target = "createTime", ignore = true),
        @Mapping(target = "createBy", ignore = true),
        @Mapping(target = "updateTime", ignore = true),
        @Mapping(target = "updateBy", ignore = true),
        @Mapping(target = "version", ignore = true),
        @Mapping(target = "deleted", ignore = true)
    })
    void updateEntity(@MappingTarget T entity, D dto);

    List<D> toDtoList(List<T> entityList);

    default Page<D> toDtoPage(Page<T> page) {
        return page.map(this::toDto);
    }

    default List<T> toEntityList(List<D> dtos) {
        if (dtos == null) return null;
        return dtos.stream()
            .map(this::toEntity)
            .collect(Collectors.toList());
    }
}