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

import java.io.Serializable;
import java.util.List;

import javax.annotation.Nullable;
import javax.inject.Inject;

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

import de.ivu.elect.business.benutzerverwaltung.boundary.AbstractBenutzerEinsatzortDAO;
import de.ivu.elect.business.benutzerverwaltung.entity.BenutzerEinsatzort;
import de.ivu.elect.business.benutzerverwaltung.entity.BenutzerEinsatzortPK;
import de.ivu.elect.business.benutzerverwaltung.entity.Rolle;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.jee.security.IpHostname;


import static de.ivu.elect.business.system.entity.SystemLogQuelle.SECURITY;
import static java.util.stream.Collectors.toList;

public abstract class AbstractBenutzerEinsatzortBestimmer implements Serializable {

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

  private static final long serialVersionUID = 1L;

  @Inject
  private transient SystemLogWriter systemLogWriter;

  @Nullable
  public BenutzerEinsatzortPK bestimmeBenutzerEinsatzort(Mandant mandant, IpHostname ipHostname) {
    String ip = ipHostname.getIp();
    if (StringUtils.isBlank(ip)) {
      LOG.warn("Keine IP-Adresse angegeben");
      return null;
    }
    List<BenutzerEinsatzort> benutzerEinsatzorte = getBenutzerEinsatzortDAO().findByAll(mandant)
        .stream().filter(be -> be.matches(ip))
        .collect(toList());

    if (benutzerEinsatzorte.isEmpty()) {
      LOG.info("Kein Benutzereinsatzort für IP-Adresse: '" + ip + "' gefunden");
      return null;
    }
    if (benutzerEinsatzorte.size() == 1) {
      BenutzerEinsatzort benutzerEinsatzort = benutzerEinsatzorte.get(0);
      LOG.info("Benutzereinsatzort für IP-Adresse: '" + ip + "' ist: " + mappeNamePattern(
          benutzerEinsatzort) + ", damit erhält der Benutzer folgende Rollen durch den Einsatzort: " + String
          .join(", ", benutzerEinsatzort.getRolles().stream().map(
              Rolle::getName).sorted().collect(toList())));
      return benutzerEinsatzort.getPk();
    }

    systemLogWriter.writeErrorLogMessageFuerMandant(mandant,
        "FEHLKONFIGURATION: Mehr als ein Benutzereinsatzort für IP-Adresse: '" + ip + "' gefunden, mögliche Treffer: " + String
            .join(", ", benutzerEinsatzorte.stream().map(this::mappeNamePattern).collect(toList())) + " - verwende KEINEN EINSATZORT(!)", SECURITY);

    return null;

  }

  protected abstract AbstractBenutzerEinsatzortDAO getBenutzerEinsatzortDAO();

  private String mappeNamePattern(BenutzerEinsatzort benutzerEinsatzort) {
    return benutzerEinsatzort.getName() + " (" + benutzerEinsatzort.getClientIpMuster() + ")";
  }

}
