package de.avatic.taricdb.helper.workbook.converters;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

import org.springframework.data.jdbc.core.mapping.AggregateReference;

import de.avatic.taricdb.helper.workbook.ExcelTable;
import de.avatic.taricdb.helper.workbook.wrapper.MeasureExclusionWrapper;
import de.avatic.taricdb.model.Geo;
import de.avatic.taricdb.model.MeasureExclusion;
import de.avatic.taricdb.service.ReferenceStorageService;

public class MeasureExclusionConverter implements ExcelTableConverter<MeasureExclusionWrapper> {

	private ReferenceStorageService referenceStorage;

	public MeasureExclusionConverter(ReferenceStorageService referenceStorage) {
		this.referenceStorage = referenceStorage;
	}

	@Override
	public Collection<MeasureExclusionWrapper> convert(ExcelTable table) {

		Collection<MeasureExclusionWrapper> exclusions = new ArrayList<>();
		Collection<Geo> geos = referenceStorage.getEntites(Geo.class);

		table.getRows().forEach((row) -> {
			if (row.index() == 0) {
				return;
			}

			String hsCode = row.getAs("Goods code", String.class);

            if(hsCode == null || hsCode.isEmpty())
                return;

			String iso3166Code = row.getAs("Excluded country", String.class);
			Integer measureCode = row.getAs("Meas. type code", Integer.class);
			Integer originCode = row.getAs("Origin code", Integer.class);
			String addCode = row.getAs("Add code", String.class);
			String orderNumber = row.getAs("Order No.", String.class);

            LocalDate startDate = row.getAs("Start date", LocalDate.class);
            LocalDate endDate = row.getAs("End date", LocalDate.class);

			Geo geo = geos.stream().filter(c -> c.getIso3166Code().equals(iso3166Code)).findAny().orElseThrow(() -> new RuntimeException("Geo not found: " + iso3166Code));

			MeasureExclusionWrapper exclusion = exclusions.stream()
					.filter(c -> c.getHsCode().equals(hsCode)
                            && c.getMeasureCode().equals(measureCode)
							&& c.getOriginCode().equals(originCode)
                            && c.getIso3166Code().equals(iso3166Code)
                            && c.getAddCode().equals(addCode)
                            && c.getOrderNumber().equals(orderNumber)
                            && Objects.equals(c.getStartDate(), startDate)
                            && Objects.equals(c.getEndDate(), endDate))
					.findAny().orElse(null);

			if (exclusion == null) {
				exclusion = new MeasureExclusionWrapper(new MeasureExclusion(AggregateReference.to(geo.getId())),
						hsCode, originCode, measureCode, iso3166Code, addCode, orderNumber, startDate, endDate);
				exclusions.add(exclusion);
			} else {
				throw new IllegalArgumentException("Duplicate measure exclusion found: measure: " + measureCode + " - origin: " + originCode + " - iso: " + iso3166Code + " - add code: " + addCode + " goods code: " +	hsCode + " order number: " + orderNumber);
			}

		});

		return exclusions;

	}

}
