
package de.ivu.elect.business.stimmeingabe.control;

import java.util.Collections;
import java.util.Map;

import javax.annotation.Nullable;

import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.gebietsbaum.entity.WahldurchfuehrungsgebietTK;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebietTK;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabeImporterGigContext;
import de.ivu.elect.jee.exchange.Violations;


import static java.util.Objects.nonNull;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.isBlank;

public class StimmeingabeImporterHelper {

  public void handleGruppeImGebietInDbNotFound(Violations violations, GruppeImGebiet gruppeImGebiet) {
    if (isBlank(gruppeImGebiet.getGruppe().getSchluessel()) && gruppeImGebiet.getVorgegebenePosition() != null) {
      violations.addError("stimmeingabe.import.gruppe.im.gebiet.nicht.vorhanden.position", gruppeImGebiet.getGebiet().getGebietTK(),
          gruppeImGebiet.getVorgegebenePosition());
    } else {
      violations.addError("stimmeingabe.import.gruppe.im.gebiet.nicht.vorhanden", gruppeImGebiet.getGruppeImGebietTK());
    }
  }

  @Nullable
  public GruppeImGebiet findGruppeImGebietBySchluessel(GruppeImGebiet gruppeImGebietInDatei, Map<GruppeImGebietTK, GruppeImGebiet> gruppenImGebietInDbPerTk,
                                                       StimmeingabeImporterGigContext gruppenImGebietInDbContext) {
    if (gruppeImGebietInDatei.getGruppe().hasSchluessel()) {
      var gruppeImGebietInDateiTk = gruppenImGebietInDbContext.getGruppeInGebietAusDateiTKCache()
          .computeIfAbsent(gruppeImGebietInDatei, GruppeImGebiet::getGruppeImGebietTK);
      return gruppenImGebietInDbPerTk.get(gruppeImGebietInDateiTk);
    }

    return null;
  }

  @Nullable
  public GruppeImGebiet findGruppeImGebietByPosition(GruppeImGebiet gruppeImGebietInDatei, StimmeingabeImporterGigContext gruppenImGebietInDbContext) {
    var positionInDatei = gruppeImGebietInDatei.getVorgegebenePosition();

    if (nonNull(positionInDatei)) {
      var gebietInDateiTk = gruppeImGebietInDatei.getGebiet().getGebietTK();

      var gruppenImGebietInDbHavingPositionInDatei = gruppenImGebietInDbContext.getGigNachGebietTkMap().getOrDefault(gebietInDateiTk, Collections.emptyList())
          .stream() //
          .filter(gruppeImGebietInDb -> pruefePositionGleich(positionInDatei, gruppeImGebietInDb, gruppenImGebietInDbContext)) //
          .collect(toList());

      if (gruppenImGebietInDbHavingPositionInDatei.size() == 1) {
        return gruppenImGebietInDbHavingPositionInDatei.get(0);
      }

      // ELECT-6189
      return gruppenImGebietInDbHavingPositionInDatei.stream()
          .filter(gruppeImGebiet -> gruppeImGebiet.hatDirektkandidatZugelassenOderUnbestimmtInGebietshierarchie(
              gruppenImGebietInDbContext.getAlleWahlvorschlaegeDerWahlInDb())
              || gruppeImGebiet.hatListeZugelassenOderUnbestimmtInGebietshierarchie(gruppenImGebietInDbContext.getAlleWahlvorschlaegeDerWahlInDb()))
          .findFirst() //
          .orElse(null);
    }

    return null;
  }

  private boolean pruefePositionGleich(Long positionInDatei, GruppeImGebiet gruppeImGebietInDb, StimmeingabeImporterGigContext gruppenImGebietInDbContext) {
    if (gruppeImGebietInDb.getVorgegebenePosition() == null) {
      var entityAufStimmzettelDaten = gruppenImGebietInDbContext.getEntityAufStimmzettelDaten();

      var wahlvorschlag = gruppeImGebietInDb.getErstenWahlvorschlagAbgeleitet(entityAufStimmzettelDaten);

      if (wahlvorschlag != null) {
        var stimmzettelPosition = wahlvorschlag.getStimmzettelPosition(gruppeImGebietInDb.getGebiet(), entityAufStimmzettelDaten).getPosition();

        if (stimmzettelPosition != null) {
          return positionInDatei.equals(stimmzettelPosition);
        }
      }
    }

    return positionInDatei.equals(gruppeImGebietInDb.getVorgegebenePosition());
  }

  public void preGebietCheck(Map<WahldurchfuehrungsgebietTK, Wahldurchfuehrungsgebiet> gebieteInDB, Wahldurchfuehrungsgebiet wahldurchfuehrungsgebietInDatei) {
    // nichts zu tun
  }

  public boolean isGruppeImGebietAufWahlvorschlagPruefen(GruppeImGebiet gruppeImGebiet) {
    return true;
  }
}
