// 服务入口，初始化所有组件并启动 HTTP 服务
package main

import (
	"fmt"
	"log"
	"os"

	"com.sclktx/m/v2/internal/admin"
	"com.sclktx/m/v2/internal/auth"
	"com.sclktx/m/v2/internal/common/middleware"
	"com.sclktx/m/v2/internal/modules/appointment"
	"com.sclktx/m/v2/internal/modules/banner"
	"com.sclktx/m/v2/internal/modules/certification"
	"com.sclktx/m/v2/internal/modules/upload"
	"com.sclktx/m/v2/internal/modules/workflow"
	"com.sclktx/m/v2/internal/pkg/config"
	"com.sclktx/m/v2/internal/pkg/database"
	"com.sclktx/m/v2/internal/pkg/dingtalk"
	"com.sclktx/m/v2/internal/pkg/minio"
	"com.sclktx/m/v2/internal/pkg/wechat"

	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	"go.uber.org/zap"

	// swagger docs
	_ "com.sclktx/m/v2/docs"
)

//	@title			来访预约管理系统 API
//	@version		1.0
//	@description	来访预约管理系统的后端API接口文档
//	@termsOfService	http://swagger.io/terms/

//	@contact.name	API Support
//	@contact.url	http://www.swagger.io/support
//	@contact.email	support@swagger.io

//	@license.name	Apache 2.0
//	@license.url	http://www.apache.org/licenses/LICENSE-2.0.html

//	@host		localhost:8080
//	@BasePath	/v1

//	@securityDefinitions.apikey	BearerAuth
//	@in							header
//	@name						Authorization

// @externalDocs.description	OpenAPI
// @externalDocs.url			https://swagger.io/resources/open-api/
func main() {
	configPath := "config/config.yaml"
	if len(os.Args) > 1 {
		configPath = os.Args[1]
	}
	cfg, err := config.LoadConfig(configPath)
	if err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}

	logger, err := zap.NewProduction()
	if err != nil {
		log.Fatalf("Failed to init logger: %v", err)
	}
	defer logger.Sync()

	db := database.InitDB(&cfg.Database)

	// 初始化基础数据（流程定义等）
	database.InitData(db, &cfg.System)

	wxClient := wechat.NewMiniProgramClient(&cfg.Wechat)

	dingTalkClient := dingtalk.NewClient(&cfg.DingTalk)

	minioClient, err := minio.NewClient(&cfg.MinIO)
	if err != nil {
		log.Printf("Warning: MinIO 初始化失败: %v", err)
	}

	gin.SetMode(cfg.Server.Mode)
	r := gin.New()

	r.Use(middleware.CORS())
	r.Use(middleware.Logger(logger))
	r.Use(gin.Recovery())

	r.GET("/health", func(c *gin.Context) {
		c.JSON(200, gin.H{"status": "ok"})
	})

	// Swagger 文档
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	v1 := r.Group("/v1")

	authHandler := auth.NewAuthHandler(db, cfg, wxClient)

	// ========== 管理员路由（使用独立管理员 JWT，优先注册避免被小程序 JWT 拦截）==========
	var adminHandler *admin.AdminHandler
	{
		adminAuthHandler := admin.NewAdminAuthHandler(db, cfg.JWT.Secret, cfg.JWT.ExpireHours)
		// 公开：管理员登录
		v1.POST("/admin/login", adminAuthHandler.Login)

		adminJWTMiddleware := middleware.AdminJWTAuth(cfg.JWT.Secret)
		// 管理员个人信息
		v1.GET("/admin/profile", adminJWTMiddleware, adminAuthHandler.GetProfile)

		// 管理员 CRUD 接口
		adminHandler = admin.NewAdminHandler(db, wxClient)
		adminHandler.RegisterRoutes(v1, adminJWTMiddleware)

		// 工作流流程定义管理（管理员后台使用）
		wfAdmin := workflow.NewHandler(db, wxClient.SendSubscribeMessage, nil)
		adminWF := v1.Group("/admin", adminJWTMiddleware)
		{
			adminWF.GET("/workflow/definitions", wfAdmin.ListDefinitions)
			adminWF.POST("/workflow/definitions", wfAdmin.CreateDefinition)
			adminWF.PUT("/workflow/definitions/:id", wfAdmin.UpdateDefinition)
			adminWF.DELETE("/workflow/definitions/:id", wfAdmin.DeleteDefinition)
			// 工作流实例查询（管理后台查看审批进度）
			adminWF.GET("/workflow/instances", wfAdmin.ListInstances)
			adminWF.GET("/workflow/instances/:id", wfAdmin.GetInstanceDetail)
		}
	}

	// 公开路由
	{
		authHandler.RegisterRoutes(v1)

		bannerHandler := banner.NewBannerHandler(db)
		bannerHandler.RegisterRoutes(v1)

		uploadHandler := upload.NewUploadHandler(wxClient, minioClient)
		uploadHandler.RegisterRoutes(v1)

		// 到访区域列表（小程序端需要）
		v1.GET("/visitor-areas", adminHandler.ListVisitorAreas)

		// 部门列表（小程序认证申请需要）
		v1.GET("/departments", adminHandler.ListAllDepartments)
	}

	// 认证路由（需要 JWT）
	authV1 := v1.Group("")
	authV1.Use(middleware.JWTAuth(cfg.JWT.Secret))
	{
		authHandler.RegisterAuthRoutes(authV1)

		appointmentHandler := appointment.NewAppointmentHandler(db, wxClient, dingTalkClient)
		appointmentHandler.RegisterRoutes(authV1)

		certificationHandler := certification.NewHandler(db)
		certificationHandler.RegisterRoutes(authV1)

		workflowHandler := workflow.NewHandler(db, wxClient.SendSubscribeMessage, dingTalkClient)
		workflowHandler.RegisterRoutes(authV1)
	}

	addr := fmt.Sprintf(":%d", cfg.Server.Port)
	logger.Info("Server starting", zap.String("addr", addr))
	log.Printf("Server is running at http://localhost%s", addr)

	if err := r.Run(addr); err != nil {
		log.Fatalf("Failed to start server: %v", err)
	}
}
