package exports

import (
	"context"
	"fmt"
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
	agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
	agendastorage "git.coopgo.io/coopgo-platform/agenda/storage"
	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
	groupsstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
	accounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
	accountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
	"github.com/gorilla/mux"
	"github.com/xuri/excelize/v2"
	"net/http"
	"sort"
)

func (h *ExportsHandler) Agenda(filter string) func(w http.ResponseWriter, r *http.Request) {
	switch filter {
	case "allEvents":
		return func(w http.ResponseWriter, r *http.Request) {
			resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{
				Namespaces: []string{"parcoursmob_dispositifs"},
			})
			if err != nil {
				fmt.Println(err)
				w.WriteHeader(http.StatusInternalServerError)
				return
			}

			events := []agendastorage.Event{}

			groupids := []string{}
			beneficiaries_ids := []string{}
			for _, e := range resp.Events {
				groupids = append(groupids, e.Owners...)
				events = append(events, e.ToStorageType())

				for _, subscriptions := range e.Subscriptions {
					beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber)
				}
			}

			sort.Sort(sorting.EventsByStartdate(events))

			groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{
				Groupids: groupids,
			})
			groups := map[string]groupsstorage.Group{}

			if err == nil {
				for _, g := range groupsresp.Groups {
					groups[g.Id] = g.ToStorageType()
				}
			}

			beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{
				Accountids: beneficiaries_ids,
			})
			if err != nil {
				fmt.Println(err)
				w.WriteHeader(http.StatusInternalServerError)
				return
			}

			beneficiaries_map := map[string]accountsstorage.Account{}
			for _, ben := range beneficiaries.Accounts {
				beneficiaries_map[ben.Id] = ben.ToStorageType()
			}

			f := h.generateExcel(events, groups, beneficiaries_map)

			h.writeFileResponse(f, w)
		}

	case "oneEvent":
		return func(w http.ResponseWriter, r *http.Request) {
			vars := mux.Vars(r)
			eventId := vars["eventid"]
			resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), &agenda.GetEventRequest{
				Id: eventId,
			})
			if err != nil {
				fmt.Println(err)
				w.WriteHeader(http.StatusInternalServerError)
				return
			}
			groupids := []string{}
			beneficiaries_ids := []string{}
			groupids = append(groupids, resp.Event.Owners...)
			for _, subscriptions := range resp.Event.Subscriptions {
				beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber)
			}
			groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{
				Groupids: groupids,
			})
			groups := map[string]groupsstorage.Group{}

			if err == nil {
				for _, g := range groupsresp.Groups {
					groups[g.Id] = g.ToStorageType()
				}
			}

			beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{
				Accountids: beneficiaries_ids,
			})
			if err != nil {
				fmt.Println(err)
				w.WriteHeader(http.StatusInternalServerError)
				return
			}

			beneficiaries_map := map[string]accountsstorage.Account{}
			for _, ben := range beneficiaries.Accounts {
				beneficiaries_map[ben.Id] = ben.ToStorageType()
			}

			f := h.generateExcel([]agendastorage.Event{resp.Event.ToStorageType()}, groups, beneficiaries_map)
			h.writeFileResponse(f, w)

		}
	}
	return nil
}

func (h *ExportsHandler) generateExcel(events []agendastorage.Event, groups map[string]groupsstorage.Group,
	beneficiaries_map map[string]accountsstorage.Account) *excelize.File {
	f := excelize.NewFile()
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()
	f.SetCellValue("Sheet1", "A1", "Evénement")
	f.SetCellValue("Sheet1", "B1", "Date de début")
	f.SetCellValue("Sheet1", "C1", "Date de fin")
	f.SetCellValue("Sheet1", "D1", "Nom bénéficiaire")
	f.SetCellValue("Sheet1", "E1", "Prenom bénéficiaire")
	f.SetCellValue("Sheet1", "F1", "Numéro allocataire / Pole emploi")
	f.SetCellValue("Sheet1", "G1", "Prescipteur")
	f.SetCellValue("Sheet1", "H1", "Prescipteur Nom")
	f.SetCellValue("Sheet1", "I1", "Gestionnaire événement")
	i := 2
	for _, e := range events {
		if len(e.Owners) == 0 {
			continue
		}
		admin := groups[e.Owners[0]]

		subscribedbygroup := ""
		subscribedbyuser := ""
		if v, ok := e.Data["subscribed_by"].(map[string]any); ok {
			if v2, ok := v["group"].(map[string]any); ok {
				if v3, ok := v2["id"].(string); ok {
					subscribedbygroup = v3
				}

			}
			if v4, ok := v["user"].(map[string]any); ok {
				if v5, ok := v4["display_name"].(string); ok {
					subscribedbyuser = v5
				}

			}
		}

		for _, s := range e.Subscriptions {

			beneficiary := beneficiaries_map[s.Subscriber]

			f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i), e.Name)
			f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i), e.Startdate.Format("2006-01-02"))
			f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i), e.Enddate.Format("2006-01-02"))
			f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i), beneficiary.Data["last_name"])
			f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i), beneficiary.Data["first_name"])
			f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i), beneficiary.Data["file_number"])
			f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i), groups[subscribedbygroup].Data["name"])
			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i), subscribedbyuser)
			f.SetCellValue("Sheet1", fmt.Sprintf("I%d", i), admin.Data["name"])
			i = i + 1
		}

	}
	return f

}

func (h *ExportsHandler) writeFileResponse(file *excelize.File, w http.ResponseWriter) {
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Disposition", "attachment; filename="+"Workbook.xlsx")
	w.Header().Set("Content-Transfer-Encoding", "binary")
	w.Header().Set("Expires", "0")
	file.Write(w)
}
