package logic

import (
	"github.com/alexedwards/scs/v2"
	conf "zeevdiukman.com/zprox/internal/config"
)

var config = conf.Get()

type App struct {
	SessionManager *scs.SessionManager
}

func (app *App) Get() *App {
	return app
}

func NewApp() *App {
	app := &App{
		SessionManager: scs.New(),
	}

	return app
}

type Groups map[string]*Group
type Group struct {
	Port string
	TLS  bool
	// ReverseProxies []string
	ReverseProxies ReverseProxies

	// Server         string
	// GroupRouter    string
}
type ReverseProxies map[string]ReverseProxy
type ReverseProxy struct {
	Certs string
}

func NewGroups() *Groups {
	grps := &Groups{}
	grps.initGroups()
	return grps
}

func (grps Groups) ForEach(fn func(k string, g *Group)) {
	for k, g := range grps {
		fn(k, g)
	}
}
func (rpxs ReverseProxies) Get() ReverseProxies {
	n := make(ReverseProxies)
	for k, v := range rpxs {
		n[k] = v
	}
	return n
}
func (rpxs ReverseProxies) Set(key string, rp ReverseProxy) ReverseProxies {
	newProxies := rpxs.Get()
	newProxies[key] = rp
	return newProxies
}

// func (rpxs ReverseProxy) Set(newRp *ReverseProxy) {
// 	rpxs = *newRp
// }

func (grps Groups) initGroups() {
	config.EntryPoints.ForEach(func(epName string, epConfig *conf.EntryPoint) {
		if _, ok := grps[epName]; !ok {
			grps[epName] = &Group{}
		}
		grps[epName].TLS = epConfig.TLS
		grps[epName].Port = epConfig.Port
	})
	config.ReverseProxies.ForEach(func(rpNameA string, rpConfigA *conf.ReverseProxy) {
		rps := grps[rpConfigA.EntryPoint].ReverseProxies
		certName := rpConfigA.TLS.Certs
		// if _, ok := rps[rpNameA]; !ok {
		// 	// grps[rpConfigA.EntryPoint] = &Group{}
		// 	// rps[rpNameA]
		// }
		rp := ReverseProxy{Certs: certName}
		a := insertValue(rps, rpNameA, rp)
		grps[rpConfigA.EntryPoint].ReverseProxies = a
	})
}

func insertValue[T any](mp map[string]T, key string, val T) map[string]T {
	n := make(map[string]T)
	for k, v := range mp {
		n[k] = v
	}
	n[key] = val
	mp = n
	return mp
	// grps[rpConfigA.EntryPoint].ReverseProxies = a
}
