package main

import (
	"fmt"
	"log"
	"net/http"

	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/casbin/casbin/v2"
	"github.com/gin-gonic/gin"
	cfg "github.com/jesusperez/cfgsrv"
)

type RouteEnv struct {
	Cfg *cfg.Config
	Users *UsersAccounts
	WebUsrs *WebAccounts
	MdlsUsrs map[string]ModelUser
	Enforcer *casbin.Enforcer
	AuthMiddleware *jwt.GinJWTMiddleware
	Store *interface{}
	RunFlags *RunFlags
}
func logRoute(c *gin.Context, rtenv *RouteEnv, ky string, info string, infoReq string) {
		  tkn := ""
			if rtenv.Cfg.UseJWT {
				tk, errtk := rtenv.AuthMiddleware.ParseToken(c)
				if errtk == nil {
					tkn = fmt.Sprintf("%v",tk.Raw)
				}
			}
			logRequest(c, rtenv, "route", rtenv.Cfg.Routes[ky].Path, info, infoReq, tkn)
}
func getRoutes(router *gin.Engine, cfg *cfg.Config, users *UsersAccounts, mdlsUsrs map[string]ModelUser, enforcer *casbin.Enforcer, store *interface{}, runFlags *RunFlags) {
	var authorized *gin.RouterGroup 
	routenv := &RouteEnv{
		Cfg: cfg,
		Users: users,
		MdlsUsrs: mdlsUsrs,
		Enforcer: enforcer,
		AuthMiddleware: nil,
		Store: store,
		RunFlags: runFlags,
	}
	if cfg.UseJWT {
	  routenv.AuthMiddleware = getJwt(routenv)
    router.POST(cfg.Routes["post_login"].Path, routenv.AuthMiddleware.LoginHandler)
		authorized = router.Group(cfg.RootAuthGroup)
		// authorized.GET(cfg.Routes["refreshauth"].Path,routenv.AuthMiddleware.RefreshHandler)
		authorized.GET(cfg.Routes["refreshauth"].Path, func(c *gin.Context) {
			get_auth_refresh_handle(c, routenv) 
		})
		authorized.Use(routenv.AuthMiddleware.MiddlewareFunc())
	} else {
    webusrs := loadWebAccounts(users)
    // router.POST(cfg.Routes["post_login"].Path, routenv.AuthMiddleware.LoginHandler)
	  authorized = router.Group(cfg.Routes["root"].Path, gin.BasicAuth(webusrs.Accounts))
	} 
	authorized.GET("/hello", func(c *gin.Context) {
		if cfg.UseJWT {
			claims := jwt.ExtractClaims(c)
			user, _ := c.Get(cfg.IdentityKey)
			c.JSON(200, gin.H{
				"userID":   claims[cfg.IdentityKey],
				"userName": user.(*User).UserName,
				"text":     "Hello World.",
			})
		} else {
				c.JSON(200, gin.H{
				"userID":   "",
				"userName": "",
				"text":     "Hello World.",
			})
		}
	})
		// authorized.GET("/page/:id", func(c *gin.Context) {
		// 	logRoute := func(info string, infoReq string) {
		// 		logRequest(c, cfg, "route", "/", info, infoReq)
		// 	}
		// 	claims := jwt.ExtractClaims(c)
		// 	user, _ := c.Get(identityKey)
	  //  	id := c.Params.ByName("id")
		// 	logRoute(fmt.Sprintf("get /"), fmt.Sprintf("get /")) 
		// 	c.HTML(http.StatusOK, "welcome", gin.H{
		// 		"title": fmt.Sprintf("Main website %s for %s (%s)",id,user.(*User).UserName,claims[identityKey]),
		// 	})
		// })
	router.GET(cfg.Routes["root"].Path, func(c *gin.Context) {
		logRoute(c,routenv,"root",fmt.Sprintf("get %s",cfg.Routes["root"].Path), fmt.Sprintf("get %s",cfg.Routes["root"].Path)) 
		c.HTML(http.StatusOK, "welcome", gin.H{
			"title": "Main website public",
		})
	})
  router.GET(cfg.Routes["page"].Path, func(c *gin.Context) {
	  get_page_handle(c, routenv )
	})
  router.GET(cfg.Routes["auth"].Path, func(c *gin.Context) {
	  get_auth_handle(c, routenv )
	})
  router.GET(cfg.Routes["invitation"].Path, func(c *gin.Context) {
	  get_invitation_handle(c, routenv )
  })
	authorized.POST(cfg.Routes["sendinvitation"].Path, func(c *gin.Context) {
	  send_invitation_handle(c, routenv )
  })
	authorized.GET(cfg.Routes["users"].Path, func(c *gin.Context) {
	  get_users_handle(c, routenv )
  })
	authorized.POST(cfg.Routes["post_users"].Path, func(c *gin.Context) {
	  post_users_handle(c, routenv )
  })
  authorized.POST(cfg.Routes["post_newuser"].Path, func(c *gin.Context) {
	  post_newuser_handle(c, routenv )
  })
	router.GET(cfg.Routes["recoveryaccess"].Path, func(c *gin.Context) {
	  get_recoveryaccess_handle(c, routenv )
  })
	router.POST(cfg.Routes["post_recoveryaccess"].Path, func(c *gin.Context) {
	  post_recoveryaccess_handle(c, routenv )
		
  })
	router.GET("/user/:name", func(c *gin.Context) {
		user := c.Params.ByName("name")
		value, ok := users.Accounts[user]
	  role := cfg.AdminRole
		if ok {
		  roles,_ := enforcer.GetUsersForRole(role)
			hasRole := false
			c.JSON(http.StatusOK, gin.H{"user": user, "value": value, "roles": roles, "hasrole": hasRole})
		} else {
			c.HTML(http.StatusOK, "index", gin.H{
				"title": "Main website",
			})
		}
	})
	// authorized.GET(cfg.Routes["data"].Path, func(c *gin.Context) {
	router.GET(cfg.Routes["data"].Path, func(c *gin.Context) {
	  get_data_handle(c, routenv )
	})
	for ky, tpl := range cfg.TemplatesFiles {
		if ky != "index" {
	    fmt.Printf("%s -> %v\n",ky,tpl)
			kyval := fmt.Sprintf("%s",ky)
			router.GET(tpl.Route, func(c *gin.Context) {
				c.HTML(http.StatusOK, kyval, gin.H{
					"title": fmt.Sprintf("%s website",kyval),
				})
			})
		}
	}
	authorized.POST(cfg.Routes["post_data"].Path, func(c *gin.Context) {
	  post_data_handle(c, routenv )
  })
	authorized.GET(cfg.Routes["trackinglist"].Path, func(c *gin.Context) {
	  get_tracking_list_handle(c, routenv )
  })
	authorized.GET(cfg.Routes["tracking"].Path, func(c *gin.Context) {
	  get_tracking_handle(c, routenv )
  })
	authorized.POST(cfg.Routes["post_tracking"].Path, func(c *gin.Context) {
	  post_tracking_handle(c, routenv )
  })
	authorized.GET(cfg.Routes["config"].Path, func(c *gin.Context) {
	  get_config_handle(c, routenv )
  })
	authorized.POST(cfg.Routes["post_config"].Path, func(c *gin.Context) {
	  post_config_handle(c, routenv )
  })
	router.GET("favicon.ico", func(c *gin.Context) {
	 	file, _ := f.ReadFile(fmt.Sprintf("%s/favicon.svg",cfg.AssetsPath))
	 	c.Data(
	 		http.StatusOK,
	 		"image/x-icon",
	 		file,
	 	)
	 })
	if cfg.UseJWT {
		router.NoRoute(routenv.AuthMiddleware.MiddlewareFunc(), func(c *gin.Context) {
			claims := jwt.ExtractClaims(c)
			log.Printf("NoRoute claims: %#v\n", claims)
			c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
		})
	} else {
		router.NoRoute(func(c *gin.Context) {
			// log.Printf("NoRoute claims: %#v\n", claims)
			c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
		})
	}
}