package server

import (
	"context"
	"fmt"
	"net/http"
	"sort"
	"strings"

	handler "git.pyer.club/kingecg/gohttpd/handler"
	"git.pyer.club/kingecg/gohttpd/model"
	logger "git.pyer.club/kingecg/gologger"
)

type RequestCtxKey string

type Route struct {
	Method  string
	Path    string
	Handler http.Handler
	matcher *UrlParamMatcher
	middles *MiddlewareLink
	wrapped bool
}

func (route *Route) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if route.wrapped == false {
		route.Handler = route.middles.WrapHandler(route.Handler)
		route.wrapped = true
	}
	route.Handler.ServeHTTP(w, r)
}

func (route *Route) Match(r *http.Request) bool {
	l := logger.GetLogger("Route")
	l.Debug(fmt.Sprintf("matching route: %s %s with %s %s", r.Method, r.URL.Path, route.Method, route.Path))
	if route.Method != "" && route.Method != r.Method {
		l.Debug("method not match")
		return false
	}

	if route.matcher != nil && route.matcher.Reg != nil {
		params, matched := MatchUrlParam(r.URL.Path, route.matcher)
		if matched {
			ctx := r.Context()
			data := ctx.Value(RequestCtxKey("data")).(map[string]interface{})
			for _, p := range route.matcher.Params {
				data[p] = params[p]
			}
			return true
		}
		l.Debug("Not match matcher reg")
		return false
	}
	if route.Path == "" {
		return true
	}
	return strings.HasPrefix(r.URL.Path, route.Path)
}

func (route *Route) Add(m Middleware) {
	route.middles.Add(m)
}

// NewRoute 返回一个新的Route实例
// 参数：
// - method: 请求方法
// - path: 请求路径
// - handleFn: http.Handler处理函数
// 返回值：
// - *Route: 一个指向Route的指针
func NewRoute(method string, path string, handleFn http.Handler) *Route {
	ret := &Route{
		Method:  method,
		Path:    path,
		middles: NewMiddlewareLink(),
		wrapped: false,
	}
	p := ParseUrl(path)
	// 使用handleFn构建handler
	ret.Handler = handleFn
	ret.matcher = &p
	return ret
}

type Routes []*Route

func (rs Routes) Less(i, j int) bool {
	iPaths := strings.Split(rs[i].Path, "/")
	jPaths := strings.Split(rs[j].Path, "/")
	if len(iPaths) > len(jPaths) {
		return true
	}
	if len(iPaths) < len(jPaths) {
		return false
	}
	for k := 0; k < len(iPaths); k++ {
		if iPaths[k] != jPaths[k] {
			return iPaths[k] < jPaths[k]
		}
	}
	return false
}

func (rs Routes) Len() int {
	return len(rs)
}

func (rs Routes) Swap(i, j int) {
	rs[i], rs[j] = rs[j], rs[i]
}

// 可以嵌套的Rest http server mux
type RestMux struct {
	Path           string
	routes         Routes
	middlewares    *MiddlewareLink
	wrapperHandler http.Handler
}

func (mux *RestMux) Use(m Middleware) {
	mux.middlewares.Add(m)
}
func (mux *RestMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if mux.wrapperHandler == nil {
		mux.wrapperHandler = mux.middlewares.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			for _, route := range mux.routes {
				if route.Match(r) {
					route.ServeHTTP(w, r)
					return
				}
			}

			http.NotFound(w, r)
		}))

	}
	mux.wrapperHandler.ServeHTTP(w, r)
	// c := r.Context()
	// newRequest := r
	// if t := c.Value("data"); t == nil {
	// 	data := map[string]interface{}{}
	// 	cn := context.WithValue(c, RequestCtxKey("data"), data)
	// 	newRequest = r.WithContext(cn)

	// }

	// if mux.middlewares.Len() > 0 && !mux.middlewares.ServeHTTP(w, newRequest) {
	// 	return
	// }

	// 根据r 从routes中找到匹配的路由

}

func (mux *RestMux) HandleFunc(method string, path string, f func(http.ResponseWriter, *http.Request)) *Route {
	r := NewRoute(method, path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		f(w, r)
	}))
	mux.routes = append(mux.routes, r)
	sort.Sort(mux.routes)
	return r
}

func (mux *RestMux) Get(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("GET", path, f)
}

func (mux *RestMux) Post(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("POST", path, f)
}

func (mux *RestMux) Put(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("PUT", path, f)
}
func (mux *RestMux) Delete(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("DELETE", path, f)
}
func (mux *RestMux) Patch(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("PATCH", path, f)
}
func (mux *RestMux) Head(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("HEAD", path, f)
}

func (mux *RestMux) Option(path string, f func(http.ResponseWriter, *http.Request)) *Route {
	return mux.HandleFunc("OPTION", path, f)
}

func (mux *RestMux) HandleMux(nmux *RestMux) *Route {
	p := nmux.Path
	if !strings.HasSuffix(p, "/") {
		p = p + "/"
	}
	r := NewRoute("", p, nmux)
	mux.routes = append(mux.routes, r)
	sort.Sort(mux.routes)
	return r
}

func NewRestMux(path string) *RestMux {
	ret := &RestMux{
		Path:        path,
		routes:      Routes{},
		middlewares: NewMiddlewareLink(),
	}
	return ret
}

type ServerMux struct {
	http.Handler
	directiveHandlers *MiddlewareLink
	handlers          map[string]http.Handler
	paths             []string
	wrappedHandler    map[string]http.Handler
}

func (s *ServerMux) Handle(pattern string, handler http.Handler) {
	if s.handlers == nil {
		s.handlers = make(map[string]http.Handler)
	}
	s.handlers[pattern] = s.directiveHandlers.WrapHandler(handler)
	s.paths = append(s.paths, pattern)
	// 自定义比较函数排序s.paths
	sort.Slice(s.paths, func(i, j int) bool {
		return len(s.paths[i]) > len(s.paths[j]) || s.paths[i] > s.paths[j]
	})
}

func (s *ServerMux) AddDirective(directiveStr string) {
	l := logger.GetLogger("ServerMux")
	strs := strings.Split(directiveStr, " ")
	directiveName := strs[0]
	params := strs[1:]
	directive, ok := DirectiveMap[directiveName]
	if ok {
		l.Debug(fmt.Sprintf("add directive: %s", directiveName))
		s.directiveHandlers.Add(directive(params...))
	} else {
		l.Error(fmt.Sprintf("directive not found: %s", directiveName))
	}
}
func (s *ServerMux) getHandler(path string) http.Handler {
	h, ok := s.handlers[path]
	if ok {
		return h
	}
	return nil
}
func (s *ServerMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	l := logger.GetLogger("Access")
	data := map[string]interface{}{}
	c := r.Context()
	cn := context.WithValue(c, RequestCtxKey("data"), data)
	newRequest := r.WithContext(cn)
	l.Info(fmt.Sprintf("From %s-%s %s", r.RemoteAddr, r.Method, r.URL.Path))
	for _, p := range s.paths {
		if strings.HasPrefix(r.URL.Path, p) {
			l.Info(fmt.Sprintf("match path: %s", p))
			fhandler := s.getHandler(p)
			if fhandler != nil {
				fhandler.ServeHTTP(w, newRequest)
				return
			}
			// s.handlers[p].ServeHTTP(w, newRequest)
			// s.directiveHandlers.ServeHTTP(w, newRequest)
			// ctx := newRequest.Context()
			// m := ctx.Value(RequestCtxKey("data")).(map[string]interface{})
			// _, ok := m["Tg"]
			// if ok {
			// 	wrappedHandler := s.wrappedHandler[p]
			// 	if wrappedHandler == nil {
			// 		s.wrappedHandler[p] = gzip.DefaultHandler().WrapHandler(s.handlers[p])
			// 		wrappedHandler = s.wrappedHandler[p]
			// 	}
			// 	wrappedHandler.ServeHTTP(w, newRequest)
			// } else {
			// 	s.handlers[p].ServeHTTP(w, newRequest)
			// }

			// return
		}
	}
	l.Error(fmt.Sprintf("404: %s", r.URL.Path))
	http.NotFound(w, newRequest)
}

// NewServeMux 根据提供的 HTTP 服务器配置创建并返回一个新的 ServerMux 实例。
// 参数:
// - c: 指向 model.HttpServerConfig 结构体的指针，包含服务器的配置信息。
// 返回值:
// - *ServerMux: 一个指向 ServerMux 的指针，用于处理 HTTP 请求。
func NewServeMux(c *model.HttpServerConfig) *ServerMux {
	// 获取名为 "ServerMux" 的日志记录器实例
	l := logger.GetLogger("ServerMux")
	// 记录创建 ServerMux 的调试信息
	l.Debug("NewServeMux")
	// 初始化一个新的 ServerMux 实例
	s := &ServerMux{
		// 初始化指令处理中间件链
		directiveHandlers: NewMiddlewareLink(),
		// 初始化处理程序映射
		handlers: make(map[string]http.Handler),
		// 初始化路径列表
		paths: []string{},
		// 初始化包装处理程序映射
		wrappedHandler: make(map[string]http.Handler),
	}

	s.AddDirective("Record-Access")
	// 遍历配置中的所有指令
	for _, directive := range c.Directives {
		// 将指令添加到 ServerMux 的指令处理中间件链中
		s.AddDirective(string(directive))
	}
	// 遍历配置中的所有 HTTP 路径
	for _, httpPath := range c.Paths {
		// 检查路径配置中是否指定了根目录
		if httpPath.Root != "" {
			// 创建一个新的文件处理程序
			fileHandler := handler.NewFileHandler(handler.FileHandler{
				WPath: httpPath.Path,
				// 设置文件处理程序的根目录
				Root: httpPath.Root,
				// 设置文件处理程序的默认文件
				Default: httpPath.Default,
			})
			// 将文件处理程序注册到 ServerMux 中
			s.Handle(httpPath.Path, fileHandler)
			// 检查路径配置中是否指定了上游服务器
		} else if len(httpPath.Upstreams) != 0 {
			// 创建一个新的代理处理程序
			proxyHandler := handler.NewProxyHandler(&httpPath)
			// 将代理处理程序注册到 ServerMux 中
			s.Handle(httpPath.Path, proxyHandler)
			// 如果既没有指定根目录也没有指定上游服务器
		} else {
			// 记录不支持的路径类型错误信息
			l.Error("Not supportted server path type :", httpPath.Path)
		}
	}
	// 返回初始化好的 ServerMux 实例
	return s
}
