package main

import (
	"flag"
	"fmt"
	"net/http"

	"sundynix-micro-go/app/gateway/internal/config"
	"sundynix-micro-go/app/gateway/internal/handler"
	"sundynix-micro-go/app/gateway/internal/middleware"
	"sundynix-micro-go/app/system/rpc/systemservice"

	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stat"
	"github.com/zeromicro/go-zero/zrpc"
)

var configFile = flag.String("f", "etc/gateway.yaml", "the config file")

func main() {
	flag.Parse()
	stat.DisableLog()

	var c config.Config
	conf.MustLoad(*configFile, &c)

	// 手动初始化日志（自定义 gateway 没用 rest.MustNewServer，需要显式设置）
	logx.MustSetup(c.Log)

	// 初始化 system-rpc 客户端（用于写操作日志）
	systemRpc := systemservice.NewSystemService(zrpc.MustNewClient(c.SystemRpc))

	// 构建反向代理路由器
	proxyRouter := handler.NewProxyRouter(c.Upstreams)

	// 构建中间件链（执行顺序：操作日志 → 鉴权 → CORS → 代理）
	// 注意：由于是外层包内层，实际请求流程是：OpLog → Auth → CORS → Proxy → CORS → Auth → OpLog
	var finalHandler http.Handler = proxyRouter

	// 注入 CORS 中间件
	if c.Cors.Enable {
		corsMiddleware := middleware.NewCorsMiddleware(c.Cors.AllowOrigins, c.Cors.AllowMethods, c.Cors.AllowHeaders)
		finalHandler = http.HandlerFunc(corsMiddleware.Handle(func(w http.ResponseWriter, r *http.Request) {
			proxyRouter.ServeHTTP(w, r)
		}))
	}

	// 注入 JWT 鉴权中间件（含滑动窗口续期）
	authMiddleware := middleware.NewAuthMiddleware(c.JwtSecret, c.AuthWhitelist)
	finalHandler = authMiddleware.Handle(finalHandler)

	// 注入操作日志中间件（在最外层，记录完整的请求-响应周期，含鉴权状态）
	opLogMiddleware := middleware.NewOperationLogMiddleware(systemRpc, c.JwtSecret)
	finalHandler = opLogMiddleware.Handle(finalHandler)

	// 健康检查
	mux := http.NewServeMux()
	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		fmt.Fprintf(w, `{"code":200,"msg":"gateway is healthy","upstreams":%d}`, len(c.Upstreams))
	})
	mux.Handle("/", finalHandler)

	addr := fmt.Sprintf("%s:%d", c.Host, c.Port)
	logx.Infof("===== Sundynix Gateway 启动 =====")
	logx.Infof("监听地址: %s", addr)
	logx.Infof("路由数量: %d", len(c.Upstreams))
	for _, u := range c.Upstreams {
		logx.Infof("  %s -> %s", u.Prefix, u.Target)
	}
	logx.Infof("中间件: CORS | JWT鉴权(滑动续期) | 操作日志→system-rpc")
	logx.Infof("鉴权白名单: %d 条", len(c.AuthWhitelist))
	logx.Infof("================================")

	if err := http.ListenAndServe(addr, mux); err != nil {
		logx.Errorf("网关启动失败: %v", err)
	}
}
