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

import de.ivu.elect.business.kandidatur.boundary.ListenkandidaturDAO;
import de.ivu.elect.business.stimmzettel.boundary.EntityAufStimmzettelDatenDAOFactory;
import de.ivu.elect.business.wahlrechtspruefung.boundary.WahlZulassungspruefungFactory;
import de.ivu.elect.business.wahlrechtspruefung.boundary.WahlrechtspruefungDAO;
import de.ivu.elect.business.wahlrechtspruefung.control.WahlZulassungspruefungNotInject;
import de.ivu.elect.business.wahlrechtspruefung.entity.NlPruefkriteriumAuswirkung;
import de.ivu.elect.business.wahlrechtspruefung.entity.NlWahlrechtspruefung;
import de.ivu.elect.business.wahlvorschlag.entity.Liste;
import de.ivu.elect.business.wahlvorschlag.entity.NlListe;
import de.ivu.elect.business.wahlvorschlag.entity.WahlvorschlagStatus;
import de.ivu.elect.util.StringJoiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.ejb.Stateless;
import javax.enterprise.inject.Specializes;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;

@Stateless
@Specializes
public class NlWusWahlvorschlagCommonEdit extends WahlvorschlagCommonEdit {

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

    @Inject
    private transient ListeDAO listeDAO;

    @Inject
    private transient EntityAufStimmzettelDatenDAOFactory entityAufStimmzettelDatenDAOFactory;

    @Inject
    private transient WahlZulassungspruefungFactory wahlZulassungspruefungFactory;

    @Inject
    private transient ListenkandidaturDAO listenkandidaturDAO;
    @Inject
    protected WahlrechtspruefungDAO wahlrechtspruefungDAO;

    @Override
    protected void setStatusInternal(Liste liste, WahlvorschlagStatus wahlvorschlagStatus) {

        NlPruefkriteriumAuswirkung nlPruefkriteriumAuswirkung = (NlPruefkriteriumAuswirkung) liste.getTransientContext()
                .computeIfAbsent(NlPruefkriteriumAuswirkung.AUSWIRKUNG_CONTEXT_KEY, x -> NlPruefkriteriumAuswirkung.LISTE);
        String wahlvorschlagBemerkungAfterAction = (String) liste.getTransientContext()
                .getOrDefault(NlPruefkriteriumAuswirkung.BEMERKUNG_AFTER_ACTION_KEY, null);
        LOG.info("Pruefung: " + nlPruefkriteriumAuswirkung + ", " + nlPruefkriteriumAuswirkung);

        List<Liste> betroffeneListen = nlPruefkriteriumAuswirkung.bestimmeListen(liste,
                () -> NlListe.getStelInformationen(liste, listeDAO.findByGruppe(liste.getGruppe()),
                        entityAufStimmzettelDatenDAOFactory.getEntityAufStimmzettelDaten(), listenkandidaturDAO),
                listeDAO);


        super.setStatusInternal(liste, wahlvorschlagStatus);

        //ELECT-11728
        String versaumnisTextFuerListe = getVersaumnisTextFuerListe(liste);

        for (Liste betroffeneListe : betroffeneListen) {
            if (!liste.equals(betroffeneListe) && isPossible(betroffeneListe, wahlvorschlagStatus)) {

                if (wahlvorschlagBemerkungAfterAction != null) { //WUS-NlListeZulassungAblehnenMitBemerkungAction

                    String versaumnisTextFuerBetroffeneListe = getVersaumnisTextFuerListe(betroffeneListe);

                    // "Es werden nur Listen in der Massenoperation abgelehnt, die die gleiche Versäumnismenge haben
                    // (also den gleichen Standardablehnungsgrund). Gleiche Versäumnismenge kann auch kein Versäumnis bedeuten."
                    if(versaumnisTextFuerListe == null && versaumnisTextFuerBetroffeneListe == null
                        || versaumnisTextFuerListe != null && versaumnisTextFuerListe.equals(versaumnisTextFuerBetroffeneListe)){

                        NlListe.setZulassungAbgelehntBegruendung(betroffeneListe, wahlvorschlagBemerkungAfterAction);
                        super.setStatusInternal(betroffeneListe, wahlvorschlagStatus);
                    }

                }else{
                    super.setStatusInternal(betroffeneListe, wahlvorschlagStatus);
                }
            }
        }
    }

    @Nullable
    private String getVersaumnisTextFuerListe(Liste liste) {
        ArrayList<String> versaeumnisse = new ArrayList<>();
        wahlrechtspruefungDAO.findByWahlvorschlag(liste).stream().filter(wahlrechtspruefung -> wahlrechtspruefung.getWahlrechtspruefStatus().isNichtErfuellt()).
                forEach(wahlrechtspruefung -> {

                    NlWahlrechtspruefung nlWahlrechtspruefung = NlWahlrechtspruefung.from(wahlrechtspruefung);
                    String bemerkung = wahlrechtspruefung.getBemerkung();
                    if (bemerkung == null) {
                        versaeumnisse.add(nlWahlrechtspruefung.formatText(nlWahlrechtspruefung.getPruefkriterium().getTextFuerProtokollNichtErfuellt()));
                    } else {
                        versaeumnisse.add(bemerkung);
                    }
                });
        if (versaeumnisse.isEmpty()) {
            return null;
        }
        return StringJoiner.joinWithCustomSeparator("\n", versaeumnisse);
    }

    private boolean isPossible(Liste liste, WahlvorschlagStatus wahlvorschlagStatus) {
        WahlZulassungspruefungNotInject wahlZulassungspruefung = wahlZulassungspruefungFactory.create(liste.getWahl());
        if (wahlvorschlagStatus.isZugelassen()) {
            return wahlZulassungspruefung.isZulassungBestaetigenZulaessig(liste) || wahlZulassungspruefung.isZulassungZuruecksetzenZulaessig(liste);
        } else if (wahlvorschlagStatus.isNichtZugelassenImSinneAbgelehnt()) {
            return wahlZulassungspruefung.isZulassungAblehnenZulaessig(liste) || wahlZulassungspruefung.isZulassungZuruecksetzenZulaessig(liste);
        } else if (wahlvorschlagStatus.isUngeprueft()) {
            return wahlZulassungspruefung.isZulassungZuruecksetzenZulaessig(liste);
        }
        return false;
    }

}
