package application

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
	mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
	"github.com/google/uuid"
	"google.golang.org/protobuf/types/known/structpb"
)

type UserForm struct {
	FirstName   string `json:"first_name" validate:"required"`
	LastName    string `json:"last_name" validate:"required"`
	Email       string `json:"email" validate:"required,email"`
	PhoneNumber string `json:"phone_number" `
	Address     any    `json:"address,omitempty"`
	Gender      string `json:"gender"`
}

func (h *ApplicationHandler) MemberDisplay(w http.ResponseWriter, r *http.Request) {

	adm := strings.Split(r.URL.Path, "/")
	adminid := adm[3]

	request := &mobilityaccounts.GetAccountRequest{
		Id: adminid,
	}

	resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	//////////////////////////////////add organisations/////////////////////////////////////////////////

	var allIds []string
	for _, v := range resp.Account.ToStorageType().Data["groups"].([]any) {
		s := fmt.Sprintf("%v", v)
		if !(strings.Contains(s, "admin")) {
			allIds = append(allIds, s)
		}
	}
	reques := &groupsmanagement.GetGroupsBatchRequest{
		Groupids: allIds,
	}

	res, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), reques)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	var groupsName []string

	for _, group := range res.Groups {
		g := fmt.Sprintf("%v", group.ToStorageType().Data["name"])
		groupsName = append(groupsName, g)
	}

	h.Renderer.MemberDisplay(w, r, resp.Account.ToStorageType(), groupsName)
}

func (h *ApplicationHandler) MemberUpdate(w http.ResponseWriter, r *http.Request) {
	adm := strings.Split(r.URL.Path, "/")
	userID := adm[3]

	if r.Method == "POST" {

		dataMap, err := parseUserForm(r)
		if err != nil {
			fmt.Println(err)
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		data, err := structpb.NewValue(dataMap)
		if err != nil {
			fmt.Println(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		request := &mobilityaccounts.UpdateDataRequest{
			Account: &mobilityaccounts.Account{
				Id:        userID,
				Namespace: "parcoursmob",
				Data:      data.GetStructValue(),
			},
		}

		resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)

		if err != nil {
			fmt.Println(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		http.Redirect(w, r, fmt.Sprintf("/app/members/%s", resp.Account.Id), http.StatusFound)

		return
	}

	request := &mobilityaccounts.GetAccountRequest{
		Id: userID,
	}

	resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	h.Renderer.MemberUpdate(w, r, resp.Account.ToStorageType())
}

func parseUserForm(r *http.Request) (map[string]any, error) {
	if err := r.ParseForm(); err != nil {
		return nil, err
	}

	formData := UserForm{
		FirstName:   r.PostFormValue("first_name"),
		LastName:    r.PostFormValue("last_name"),
		Email:       r.PostFormValue("email"),
		PhoneNumber: r.PostFormValue("phone_number"),
		Gender:      r.PostFormValue("gender"),
	}

	validate := formvalidators.New()
	if err := validate.Struct(formData); err != nil {
		return nil, err
	}

	d, err := json.Marshal(formData)
	if err != nil {
		return nil, err
	}

	var dataMap map[string]any
	err = json.Unmarshal(d, &dataMap)
	if err != nil {
		return nil, err
	}

	return dataMap, nil
}

func (h *ApplicationHandler) MembersList(w http.ResponseWriter, r *http.Request) {

	accounts, err := h.services.GetAccounts()
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	var groupsName []string

	for _, v := range accounts {
		adminid := v.ID
		request := &mobilityaccounts.GetAccountRequest{
			Id: adminid,
		}

		resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request)
		if err != nil {
			fmt.Println(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		//////////////////////////////////add organisations/////////////////////////////////////////////////

		var allIds []string
		for _, v := range resp.Account.ToStorageType().Data["groups"].([]any) {
			s := fmt.Sprintf("%v", v)
			if !(strings.Contains(s, "admin")) {
				allIds = append(allIds, s)
			}

		}

		reques := &groupsmanagement.GetGroupsBatchRequest{
			Groupids: allIds,
		}

		res, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), reques)
		if err != nil {
			fmt.Println(err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		g := ""
		for _, group := range res.Groups {
			g += fmt.Sprintf("%v", group.ToStorageType().Data["name"]) + " "
		}
		groupsName = append(groupsName, g)

	}
	cacheid := uuid.NewString()
	h.cache.PutWithTTL(cacheid, accounts, 1*time.Hour)

	h.Renderer.MembersList(w, r, accounts, cacheid, groupsName)
}
