package com.eactive.eai.rms.onl.transaction.apim.mapping;


import com.eactive.apim.portal.apispec.entity.ApiSpecInfo;
import com.eactive.apim.portal.apispec.repository.ApiSpecInfoRepository;
import com.eactive.eai.data.mapper.BaseMapperConfig;
import com.eactive.eai.rms.onl.manage.serviceinfo.stdmessage.StdMessageItemUIMapper;
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiSpecInfoUI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.mapstruct.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Mapper(config = BaseMapperConfig.class, uses = {StdMessageItemUIMapper.class})
@Component
public abstract class ApiSpecUIMapper {

    @Autowired
    private ApiSpecInfoRepository apiSpecInfoRepository;

    public abstract ApiSpecInfoUI mapToUI(ApiSpecInfo apiSpecInfo);

    public abstract ApiSpecInfo mapToEntity(ApiSpecInfoUI apiSpecInfoUI);

    public ApiSpecInfoUI map(Optional<ApiSpecInfo> optionalApiSpecInfo) {
        return optionalApiSpecInfo.map(this::mapToUI).orElse(new ApiSpecInfoUI());
    }

    public ApiSpecInfo getById(String id) {
        return apiSpecInfoRepository.findById(id).orElse(null);
    }

    public ApiSpecInfoUI getUIById(String id) {
        return mapToUI(apiSpecInfoRepository.findById(id).orElse(null));
    }

    public List<ApiSpecInfo> mapList(List<ApiSpecInfoUI> apiSpecInfoUIList) {
        if (apiSpecInfoUIList == null || apiSpecInfoUIList.isEmpty()) {
            return Collections.emptyList();
        }

        // Extract all API IDs
        List<String> apiIds = apiSpecInfoUIList.stream()
            .map(ApiSpecInfoUI::getApiId)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());

        // Batch fetch all API specs at once
        Map<String, ApiSpecInfo> apiSpecMap = apiSpecInfoRepository.findAllById(apiIds)
            .stream()
            .collect(Collectors.toMap(
                ApiSpecInfo::getApiId,
                Function.identity(),
                (existing, replacement) -> existing // Keep first in case of duplicates
            ));

        // Map UI objects to domain objects, preserving order and handling missing entries
        return apiSpecInfoUIList.stream()
            .map(ui -> ui.getApiId() != null ? apiSpecMap.get(ui.getApiId()) : null)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }
}
