package authentication

import (
	"context"
	"net/http"

	d "github.com/karincake/dodol"
	rw "github.com/karincake/risoles"
	sp "github.com/karincake/semprit"
	sr "github.com/karincake/serabi"

	m "simrs-vx/internal/domain/main-entities/user"
	mf "simrs-vx/internal/domain/main-entities/user-fes"
	pa "simrs-vx/internal/lib/auth"
	s "simrs-vx/internal/use-case/main-use-case/authentication"
)

func Login(w http.ResponseWriter, r *http.Request) {
	var input m.LoginDto
	if !(rw.ValidateStructByIOR(w, r.Body, &input)) {
		return
	}

	// input.Position = Position
	res, err := s.GenToken(input)
	if err != nil {
		rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil)
	} else {
		rw.DataResponse(w, res, err)
	}
}

func LoginFes(w http.ResponseWriter, r *http.Request) {
	var input mf.LoginDto
	err := sp.IOReaderJson(&input, r.Body)
	if err != nil {
		rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil)
		return
	}

	input.AuthPartner_Code = r.Header.Get("X-AuthPartner-Code")
	input.AuthPartner_SecretKey = r.Header.Get("X-AuthPartner-SecretKey")
	if err = sr.Validate(input); err != nil {
		rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil)
		return
	}

	// input.Position = Position
	res, err := s.GenTokenFes(input)
	if err != nil {
		rw.WriteJSON(w, http.StatusUnauthorized, d.II{"errors": err}, nil)
	} else {
		rw.DataResponse(w, res, err)
	}
}

func Logout(w http.ResponseWriter, r *http.Request) {
	ctxVal := r.Context().Value(pa.AuthKey{})
	if ctxVal == nil {
		rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "logout skiped. the request is done wihtout authorization."}, nil)
		return
	}
	authInfo := ctxVal.(*pa.AuthInfo)
	s.RevokeToken(authInfo.Uuid)
	rw.WriteJSON(w, http.StatusOK, d.IS{"message": "logged out"}, nil)
}

func GuardMW(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		accessDetail, err := s.ExtractToken(r, s.AccessToken)
		if err != nil {
			rw.WriteJSON(w, http.StatusUnauthorized, err.(d.FieldError), nil)
			return
		}
		ctx := context.WithValue(r.Context(), pa.AuthKey{}, accessDetail)
		next.ServeHTTP(w, r.WithContext(ctx))
	})
}
