
package de.ivu.elect.business.wahl.boundary;

import java.util.List;

import javax.annotation.Nullable;
import javax.ejb.Stateless;
import javax.enterprise.inject.Specializes;
import javax.inject.Inject;
import javax.persistence.NoResultException;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.CurrentCustomer;
import de.ivu.elect.business.datei.entity.DateiImport;
import de.ivu.elect.business.exchange.entity.ImportUpdateReport;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.wahl.control.Wahldaten;
import de.ivu.elect.business.wahl.entity.NlWahlCustomData;
import de.ivu.elect.business.wahl.entity.NlWahlart;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlImportContext;
import de.ivu.elect.business.wahl.entity.Wahlart;
import de.ivu.elect.business.wahl.entity.WahlartSitzberechnungsalgorithmus;
import de.ivu.elect.business.wahl.entity.Wahldurchfuehrung;
import de.ivu.elect.jee.exchange.ImportOptions;
import de.ivu.elect.jee.exchange.Violations;
import de.ivu.elect.presentation.NlElectionLevel;
import de.ivu.elect.presentation.NlSystemProperties;

@Stateless
@Specializes
public class NlWasWahlImporter extends WasWahlImporter {

  private static final Logger LOG = LoggerFactory.getLogger(NlWasWahlImporter.class);

  @Inject
  private transient NlWahlImportHelper nlWahlImportHelper;

  @Inject
  private transient CurrentCustomer currentCustomer;

  @Inject
  private transient NlSystemProperties nlSystemProperties;

  public NlWasWahlImporter() {
    super();
  }

  @Nullable
  @Override
  protected Wahlart findeWahlartInDb(Wahlart wahlart, WahlImportContext context) {
    return nlWahlImportHelper.findeWahlartInDb(wahlart, context);
  }

  @Override
  protected void preImportActions(DateiImport dateiImport, WahlImportContext wahlImportContext, ImportOptions importOptions) {
    super.preImportActions(dateiImport, wahlImportContext, importOptions);
    wahlImportContext.put("Eml110Filename", dateiImport.getDatei().getOriginalDateiname()); // ELECT-10358
  }

  @Override
  protected void updateWahlBeforePersist(WahlImportContext context, Wahl wahl) {
    nlWahlImportHelper.updateWahlBeforePersist(context, wahl);

    super.updateWahlBeforePersist(context, wahl);

    macheWahlEindeutig(wahl); // ELECT-13397

    NlWahlCustomData nlWahlCustomData = wahl.getCustomData(NlWahlCustomData.class);
    NlElectionLevel electionLevel = nlSystemProperties.getDefaultElectionLevel(context.getMandant());

    nlWahlCustomData.setNbsbSystem(electionLevel.isNBSB()); // ELECT-16655
    nlWahlCustomData.setNbsbcSystem(electionLevel.isNBSBC());

    nlWahlCustomData.setHsbbSystem(electionLevel.isHSBB()); // ELECT-16695
    nlWahlCustomData.setHsbcSystem(electionLevel.isHSBC()); // ELECT-15712
  }

  private void macheWahlEindeutig(Wahl wahl) {
    try {
      Wahl wahlMitGleichemUK = wahlDAO.findByUK(wahl.getWahlUK());

      if (wahlMitGleichemUK == null) {
        return;
      }
    } catch (NoResultException expected) {
      return;
    }

    LOG.info("Wahl nicht eindeutig: {}", wahl.getWahlUK());

    wahl.getWahltermin().setNummer(wahl.getWahltermin().getNummer() + "1");

    macheWahlEindeutig(wahl);
  }

  @Override
  protected void postCreateGebiete(List<Gebiet> gebiete) {
    super.postCreateGebiete(gebiete);

    nlWahlImportHelper.postCreateGebiete(gebiete);
  }

  @Override
  protected List<Gebiet> filterZuImportierendeGebiete(Wahldaten<Wahl, Gebiet> wahldaten, Wahlart wahlartInDb) {
    return nlWahlImportHelper.filterZuImportierendeGebiete(wahldaten, wahlartInDb);
  }

  @Override
  protected boolean isPersistiereGruppeImGebiet(GruppeImGebiet gruppeImGebiet) {
    return super.isPersistiereGruppeImGebiet(gruppeImGebiet) && gruppeImGebiet.getGebiet().isPersistent() /*ELECT-9931*/;
  }

  @Override
  protected void postCreateWahl(Wahl wahl, WahlImportContext wahlImportContext) {
    if (!NlWahlart.isWasCSB(wahl, currentCustomer.getCustomer())) {
      wahl.castTo(Wahldurchfuehrung.class).getEntity().setSitzberechnungsalgorithmus(WahlartSitzberechnungsalgorithmus.KEIN); // nur im CSB
    }
  }

  @Override
  protected boolean isLoggeVeraenderteWahlparameter() {
    return false; // ELECT-11334
  }

  @Override
  protected void validiereWahl(WahlImportContext context, Wahldaten<Wahl, Gebiet> wahldaten, Violations violations) {
    super.validiereWahl(context, wahldaten, violations);

    String abWatershap = wahldaten.getWahl().getCustomData(NlWahlCustomData.class).getAbWatershap();

    if (StringUtils.isNotBlank(abWatershap)) {
      for (Wahl wahl : wahlDAO.findByAll(context.getMandant())) {
        if (abWatershap.equals(wahl.getCustomData(NlWahlCustomData.class).getAbWatershap())) {
          violations.addError("nl.was.wahl.import.watershap.bereits.vorhanden", abWatershap);
        }
      }
    }
  }

  @Override
  protected ImportUpdateReport handleImportViolationException(DateiImport dateiImport, ImportOptions importOptions, Violations violations, Exception ex) {
    if (ex instanceof NlWahlartNichtGefundenException) {
      NlWahlartNichtGefundenException nichtGefundenException = (NlWahlartNichtGefundenException) ex;

      violations.addError("importer.importieren.exception.wahlart.level", getMessage(nichtGefundenException.getNlWahlart()), getMessage(nichtGefundenException.getNlElectionLevel()));

      return new ImportUpdateReport(violations, 0, 0, 0, importOptions, new StringBuilder());
    }

    return super.handleImportViolationException(dateiImport, importOptions, violations, ex);
  }
}
