package de.avatic.taricdb.service;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import de.avatic.taricdb.helper.workbook.wrapper.AppliedMeasureWrapper;
import de.avatic.taricdb.helper.workbook.wrapper.ImportWrapper;
import de.avatic.taricdb.model.AdditionalCode;
import de.avatic.taricdb.model.AppliedMeasure;
import de.avatic.taricdb.model.Geo;
import de.avatic.taricdb.model.GeoGroup;
import de.avatic.taricdb.model.Import;
import de.avatic.taricdb.model.Nomenclature;

@Service
public class AsyncSetupDutiesService {

	private static final Logger logger = LoggerFactory.getLogger(AsyncSetupDutiesService.class);

	@Autowired
	ReferenceStorageService referenceStorage;


	@Async
	public void setupDuties(ImportWrapper im) {
		
		String hsCode = im.getHsCode();
		String origin = im.getOrigin();
		String addCode = im.getAddCode();
		
		Collection<Geo> geos = referenceStorage.getEntites(Geo.class);
		Collection<GeoGroup> geoGroups = referenceStorage.getEntites(GeoGroup.class);
		Collection<AppliedMeasureWrapper> appliedMeasures = referenceStorage.getEntites(AppliedMeasureWrapper.class);
		Collection<AdditionalCode> additionalCodes = referenceStorage.getEntites(AdditionalCode.class);
		Collection<Nomenclature> nomenclatures = referenceStorage.getEntites(Nomenclature.class);

		Nomenclature nomenclature = nomenclatures.stream().filter(n -> n.getHscode().equals(hsCode)).findFirst().orElse(null);
		AdditionalCode additionalCode = additionalCodes.stream().filter(a -> a.getAdditionalCode().equals(addCode)).findFirst().orElse(null);
		Set<AppliedMeasure> foundAppliedMeasures = appliedMeasures.stream().filter(a -> a.getHsCode().equals(hsCode) && a.getOrigin().equals(origin) && a.getAdditionalCode().equals(addCode)).map(AppliedMeasureWrapper::getAppliedMeasure).collect(Collectors.toSet());
		
		Geo geo = geos.stream().filter(g -> g.getIso3166Code().equals(origin)).findFirst().orElse(null);
		GeoGroup geoGroup = geoGroups.stream().filter(g -> g.getGeoGroupCode().equals(origin)).findFirst().orElse(null);

        if( nomenclature == null ) {
            logger.error("No nomenclature found for duty: {}", hsCode);
            im.completeImport(null);
        }
        else {
		    im.completeImport(new Import(AggregateReference.to(nomenclature.getId()), additionalCode == null ? null : AggregateReference.to(additionalCode.getId()), foundAppliedMeasures, geo == null ? null : AggregateReference.to(geo.getId()), geoGroup == null ? null : AggregateReference.to(geoGroup.getId())));
        }



	}
}
