package ldap

import (
	"net"

	"github.com/nmcclain/ldap"
	"github.com/prometheus/client_golang/prometheus"
	"goauthentik.io/internal/outpost/ldap/bind"
	"goauthentik.io/internal/outpost/ldap/metrics"
	"goauthentik.io/internal/utils"
)

func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LDAPResultCode, error) {
	req, span := bind.NewRequest(bindDN, bindPW, conn)

	defer func() {
		span.Finish()
		metrics.Requests.With(prometheus.Labels{
			"outpost_name": ls.ac.Outpost.Name,
			"type":         "bind",
			"filter":       "",
			"dn":           req.BindDN,
			"client":       req.RemoteAddr(),
		}).Observe(float64(span.EndTime.Sub(span.StartTime)))
		req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Bind request")
	}()
	for _, instance := range ls.providers {
		username, err := instance.binder.GetUsername(bindDN)
		if err == nil {
			return instance.binder.Bind(username, req)
		} else {
			req.Log().WithError(err).Debug("Username not for instance")
		}
	}
	req.Log().WithField("request", "bind").Warning("No provider found for request")
	metrics.RequestsRejected.With(prometheus.Labels{
		"outpost_name": ls.ac.Outpost.Name,
		"type":         "bind",
		"reason":       "no_provider",
		"dn":           bindDN,
		"client":       utils.GetIP(conn.RemoteAddr()),
	}).Inc()
	return ldap.LDAPResultOperationsError, nil
}
