package identification

import (
	"context"
	"fmt"
	"net/http"

	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
)

const GroupKey ContextKey = "group"
const RolesKey ContextKey = "roles"

func (p *IdentificationProvider) GroupsMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		claims := r.Context().Value(ClaimsKey).(map[string]any)

		session, _ := p.SessionsStore.Get(r, "parcoursmob_session")

		o, ok := session.Values["organization"]
		if !ok || o == nil {
			fmt.Println("no organization")
			http.Redirect(w, r, "/auth/groups/", http.StatusFound)
			return
		}

		org := o.(string)

		claimgroups, ok := claims["groups"].([]any)

		if !ok {
			fmt.Println("cast issue")
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		for _, group := range claimgroups {
			if group == org {

				request := &groupsmanagement.GetGroupRequest{
					Id: group.(string),
				}

				resp, err := p.Services.GRPC.GroupsManagement.GetGroup(context.TODO(), request)
				if err != nil {
					delete(session.Values, "organization")
					session.Save(r, w)
					http.Redirect(w, r, "/auth/groups/", http.StatusFound)
					return
				}

				ctx := context.WithValue(r.Context(), GroupKey, resp.Group.ToStorageType())

				roles := map[string]bool{}

				for _, role := range claimgroups {
					//TODO handle flexible roles / roles discovery
					if role == fmt.Sprintf("%s:admin", org) {
						roles[role.(string)] = true
					}
				}

				ctx = context.WithValue(ctx, RolesKey, roles)

				next.ServeHTTP(w, r.WithContext(ctx))
				return
			}
		}

		// Session organization is not in the available groups
		delete(session.Values, "organization")
		session.Save(r, w)
		http.Redirect(w, r, "/auth/groups/", http.StatusFound)
	})
}
