package renderer
import (
	"fmt"
	"html/template"
	"net/http"
	"git.coopgo.io/coopgo-apps/parcoursmob/core/utils/icons"
	"git.coopgo.io/coopgo-apps/parcoursmob/core/utils/identification"
	cache "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/storage"
	xlsxrenderer "git.coopgo.io/coopgo-apps/parcoursmob/renderer/xlsx"
	"git.coopgo.io/coopgo-platform/emailing"
	"git.coopgo.io/coopgo-platform/groups-management/storage"
	"github.com/coreos/go-oidc/v3/oidc"
	"github.com/rs/zerolog/log"
	"github.com/spf13/viper"
)
type Renderer struct {
	TemplatesDir string
	GlobalConfig *viper.Viper
	ThemeConfig  *viper.Viper
	Mailer       *emailing.Mailer
	FileStorage  cache.FileStorage
	XLSX         *xlsxrenderer.XLSXRenderer
}
func NewRenderer(global *viper.Viper, templates_dir string, filestorage cache.FileStorage) *Renderer {
	theme := viper.New()
	theme.SetConfigName("config")
	theme.AddConfigPath(templates_dir)
	err := theme.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("fatal error config file: %w", err))
	}
	return &Renderer{
		TemplatesDir: templates_dir,
		GlobalConfig: global,
		ThemeConfig:  theme,
		FileStorage:  filestorage,
		XLSX:         xlsxrenderer.NewXLSXRenderer(global),
	}
}
func (renderer *Renderer) Render(name string, w http.ResponseWriter, r *http.Request, files []string, state RenderState) {
	genericFiles := renderer.ThemeConfig.GetStringSlice("views.generic.files")
	prefixed_files := []string{}
	for _, f := range genericFiles {
		prefixed_files = append(prefixed_files, renderer.templateFile(f))
	}
	for _, f := range files {
		prefixed_files = append(prefixed_files, renderer.templateFile(f))
	}
	w.WriteHeader(http.StatusOK)
	t := template.New(name).Funcs(GetTemplateFuncMap(state.Group, renderer.GlobalConfig, renderer.FileStorage))
	t = template.Must(t.ParseFiles(prefixed_files...))
	err := t.ExecuteTemplate(w, "main", state)
	if err != nil {
		log.Error().Err(err).Msg("issue executing template")
	}
}
func (renderer *Renderer) RenderNoLayout(name string, w http.ResponseWriter, r *http.Request, files []string, state RenderState) {
	prefixed_files := []string{}
	for _, f := range files {
		prefixed_files = append(prefixed_files, renderer.templateFile(f))
	}
	w.WriteHeader(http.StatusOK)
	t := template.New(name).Funcs(GetTemplateFuncMap(state.Group, renderer.GlobalConfig, renderer.FileStorage))
	t = template.Must(t.ParseFiles(prefixed_files...))
	err := t.ExecuteTemplate(w, "main", state)
	if err != nil {
		log.Error().Err(err).Msg("issue executing template")
	}
}
func (r *Renderer) templateFile(file string) string {
	return r.TemplatesDir + file
}
type RenderState struct {
	icons.IconSet
	LayoutState
	UserID     string
	UserClaims map[string]any
	Group      storage.Group
	Roles      any
	ViewState  any // This is a state specific to a given view
}
func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) RenderState {
	iconset := themeConfig.GetStringMapString("icons.svg")
	menu := themeConfig.Get("menu_items")
	// Get State elements from Request
	var userid string
	var claims map[string]any
	u := r.Context().Value(identification.IdtokenKey)
	if u != nil {
		if current_user_token, ok := u.(*oidc.IDToken); ok {
			userid = current_user_token.Subject
		}
		c := r.Context().Value(identification.ClaimsKey)
		if c != nil {
			if current_user_claims, ok := c.(map[string]any); ok {
				claims = current_user_claims
			}
		}
	}
	g := r.Context().Value(identification.GroupKey)
	if g == nil {
		return RenderState{
			IconSet:     icons.NewIconSet(iconset),
			LayoutState: LayoutState{},
		}
	}
	var roles map[string]any
	ro, ok := r.Context().Value(identification.RolesKey).(map[string]any)
	if ok {
		roles = ro
	}
	group := g.(storage.Group)
	modules := group.Data["modules"].(map[string]any)
	ls := LayoutState{
		AdministrationState: AdministrationState{
			Display: modules["administration"] != nil && modules["administration"].(bool),
			Active:  menuState == administrationMenu,
		},
		Menu:       menu,
		ActiveMenu: menuState,
		// DEPRECATED
		MenuItems: []MenuItem{
			{
				Title:  "Tableau de bord",
				Link:   "/app/",
				Active: menuState == dashboardMenu,
				Icon:   "hero:outline/home",
			},
		},
	}
	// DEPRECATED
	if modules["beneficiaries"] != nil && modules["beneficiaries"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Bénéficiaires",
			Link:   "/app/beneficiaries/",
			Active: menuState == beneficiariesMenu,
			Icon:   "hero:outline/user-group",
		})
	}
	if modules["journeys"] != nil && modules["journeys"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Déplacements",
			Link:   "/app/journeys/",
			Active: menuState == journeysMenu,
			Icon:   "hero:outline/map",
		})
	}
	if modules["solidarity_transport"] != nil && modules["solidarity_transport"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Transport solidaire",
			Link:   "/app/solidarity-transport/",
			Active: menuState == solidarityTransportMenu,
			Icon:   "tabler-icons:car",
		})
	}
	if modules["vehicles"] != nil && modules["vehicles"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Véhicules partagés",
			Link:   "/app/vehicles/",
			Active: menuState == vehiclesMenu,
			Icon:   "tabler-icons:car",
		})
	}
	if modules["vehicles_management"] != nil && modules["vehicles_management"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Gestion des véhicules",
			Link:   "/app/vehicles-management/",
			Active: menuState == vehiclesmanagementMenu,
			Icon:   "hero:outline/briefcase",
		})
	}
	if modules["agenda"] != nil && modules["agenda"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Agenda dispositifs",
			Link:   "/app/agenda/",
			Active: menuState == agendaMenu,
			Icon:   "hero:outline/calendar",
		})
	}
	if modules["group_module"] != nil && modules["group_module"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Groupes / Communautés",
			Link:   "/app/group_module/",
			Active: menuState == groupMenu,
			Icon:   "hero:outline/group_module",
		})
	}
	if modules["support"] != nil && modules["support"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Support",
			Link:   "/app/support/",
			Active: menuState == commentMenu,
			Icon:   "hero:outline/support",
		})
	}
	if modules["directory"] != nil && modules["directory"].(bool) {
		ls.MenuItems = append(ls.MenuItems, MenuItem{
			Title:  "Répertoire solutions",
			Link:   "/app/directory/",
			Active: menuState == directoryMenu,
			Icon:   "hero:outline/document-text",
		})
	}
	return RenderState{
		IconSet:     icons.NewIconSet(iconset),
		Group:       group,
		Roles:       roles,
		UserID:      userid,
		UserClaims:  claims,
		LayoutState: ls,
	}
}