package api

import (
	"context"
	"crypto/ed25519"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"io/fs"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"git.zkcoi.com/zkcoi/meshray/internal/api/handler"
	"git.zkcoi.com/zkcoi/meshray/internal/api/middleware"
	"git.zkcoi.com/zkcoi/meshray/internal/config"
	"git.zkcoi.com/zkcoi/meshray/internal/ctr"
	corehandler "git.zkcoi.com/zkcoi/meshray/internal/handler"
	"git.zkcoi.com/zkcoi/meshray/internal/model"
	"git.zkcoi.com/zkcoi/meshray/internal/service"
	"git.zkcoi.com/zkcoi/meshray/internal/store/sqlite"
	"git.zkcoi.com/zkcoi/meshray/web"
	"github.com/gin-gonic/gin"
	"github.com/shirou/gopsutil/v4/cpu"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// Server API 服务器
type Server struct {
	engine    *gin.Engine
	config    *config.Config
	logger    *zap.Logger
	store     *sqlite.Store
	ctrClient *ctr.Ctr // 全局 Ctr 实例
}

// NewServer 创建 API 服务器
func NewServer(cfg *config.Config, logger *zap.Logger, dbStore *sqlite.Store) (*Server, error) {
	// 设置 Gin 模式
	switch cfg.Server.Mode {
	case "debug":
		gin.SetMode(gin.DebugMode)
	case "release":
		gin.SetMode(gin.ReleaseMode)
	default:
		gin.SetMode(gin.TestMode)
	}

	engine := gin.New()

	server := &Server{
		engine: engine,
		config: cfg,
		logger: logger,
		store:  dbStore,
	}

	// 首次启动初始化管理员账户（已存在则跳过，仅新建时返回随机密码）
	userService := service.NewUserService(dbStore)
	if uname, pwd, ierr := userService.InitializeAdmin(); ierr == nil {
		if pwd != "" {
			server.logger.Warn("已创建默认管理员账户，请尽快登录并修改密码",
				zap.String("username", uname), zap.String("password", pwd))
		}
	} else {
		server.logger.Error("初始化管理员账户失败", zap.Error(ierr))
	}

	// 注册中间件
	server.registerMiddleware()

	// 注册路由
	if err := server.registerRoutes(); err != nil {
		return nil, err
	}

	return server, nil
}

// registerMiddleware 注册全局中间件
func (s *Server) registerMiddleware() {
	// 恢复中间件
	s.engine.Use(gin.Recovery())

	// 请求日志中间件
	s.engine.Use(middleware.RequestLogger(s.logger))

	// CORS 中间件（开发环境）
	if s.config.Server.Mode != "release" {
		s.engine.Use(middleware.CORS())
	}
}

// registerRoutes 注册所有路由
func (s *Server) registerRoutes() error {
	// 健康检查
	s.engine.GET("/health", func(c *gin.Context) {
		c.JSON(200, gin.H{"status": "ok"})
	})

	// 静态文件服务（前端）
	// 使用 embed 的静态文件
	var staticFS fs.FS
	var useEmbed bool

	// 直接使用 web 包中的 WebAssets，剥离外层的 static 目录
	if embedFS, err := fs.Sub(web.WebAssets, "static"); err == nil {
		// 检查是否有 index.html
		if _, statErr := fs.Stat(embedFS, "index.html"); statErr == nil {
			staticFS = embedFS
			useEmbed = true
			s.logger.Info("使用内嵌的静态文件")
		} else {
			s.logger.Warn("embed 中找不到 index.html", zap.Error(statErr))
		}
	} else {
		s.logger.Warn("embed 文件系统创建失败", zap.Error(err))
	}

	// 如果 embed 没有内容，使用外部目录
	if !useEmbed && s.config.Server.StaticPath != "" {
		staticFS = os.DirFS(s.config.Server.StaticPath)
		s.logger.Info("使用外部静态文件目录", zap.String("path", s.config.Server.StaticPath))
	}

	if staticFS != nil {
		// ✅ 注册根路径处理
		s.engine.GET("/", func(c *gin.Context) {
			file, err := staticFS.Open("index.html")
			if err == nil {
				defer file.Close()
				content, _ := io.ReadAll(file)
				c.Data(200, "text/html; charset=utf-8", content)
				return
			}
			c.String(500, "Failed to load index.html")
		})

		// ✅ 简化：只注册 NoRoute 处理 SPA 路由
		s.engine.NoRoute(func(c *gin.Context) {
			path := c.Request.URL.Path

			// 如果是 API 请求，返回 404
			if strings.HasPrefix(path, "/api/") {
				c.JSON(404, gin.H{"error": "API not found"})
				return
			}

			// 尝试直接提供文件
			// staticFS 已通过 fs.Sub 剥离 "static" 前缀，需先去掉路径中的 "static/"
			filePath := strings.TrimPrefix(path, "/")
			filePath = strings.TrimPrefix(filePath, "static/")
			if filePath == "" {
				filePath = "index.html"
			}

			// 读取并返回文件内容
			file, err := staticFS.Open(filePath)
			if err == nil {
				defer file.Close()
				content, _ := io.ReadAll(file)
				c.Data(200, getContentType(filePath), content)
				return
			}

			// 其他请求都返回 index.html（SPA 路由支持）
			file, _ = staticFS.Open("index.html")
			if file != nil {
				defer file.Close()
				content, _ := io.ReadAll(file)
				c.Data(200, "text/html; charset=utf-8", content)
			}
		})
	} else {
		s.logger.Warn("未配置静态文件路径，前端将不可用")
	}

	// API v1 路由组
	v1 := s.engine.Group("/api/v1")
	{
		// 公开接口（无需鉴权）
		public := v1.Group("")
		{
			public.POST("/auth/login", middleware.LoginHandler(s.config.JWT.Secret, s.logger, s.store))
			public.POST("/auth/refresh", middleware.RefreshTokenHandler(s.config.JWT.Secret, s.logger))
		}

		// ✅ 提前初始化 ctrClient（在路由注册前）
		var err error
		s.ctrClient, err = ctr.NewCtr("default", 1, &ctr.CtrConfig{}, s.logger)
		if err != nil {
			s.logger.Error("初始化 meshray-ctr 失败", zap.Error(err))
			return fmt.Errorf("初始化 ctr 失败：%w", err)
		}

		// 需要鉴权的接口
		protected := v1.Group("")
		protected.Use(middleware.JWTAuth(s.config.JWT.Secret))
		{
			// 初始化 Service 层（注入 ctr 客户端）
			networkService := service.NewNetworkService(s.store, s.ctrClient, s.logger)
			deviceService := service.NewDeviceService(s.store, s.ctrClient)
			userService := service.NewUserService(s.store)
			policyService := service.NewPolicyService(s.store)
			settingsService := service.NewSettingsService(s.store, s.logger)
			pendingJoinService := service.NewPendingJoinService(s.store)

			// 初始化 MeshSeedService（需要 Ed25519 签名密钥）
			signingKey, err := s.loadSigningKey()
			if err != nil {
				s.logger.Error("加载签名密钥失败", zap.Error(err))
				return fmt.Errorf("加载签名密钥失败：%w", err)
			}
			meshSeedService := service.NewMeshSeedService(s.store, s.logger, signingKey, "node-1")

			// 初始化 SystemConfigService（系统配置服务）
			systemConfigService := service.NewSystemConfigService(s.store, s.logger)

			// 初始化 ExternalService 相关 Handler
			serviceService := service.NewServiceService(s.store)
			serviceHandler := handler.NewServiceHandler(serviceService, s.logger)

			// 初始化 SystemConfigHandler（系统配置处理器）
			systemConfigHandler := handler.NewSystemConfigHandler(systemConfigService, s.logger)

			// 初始化 PendingJoinHandler（待审核处理器）
			pendingJoinHandler := handler.NewPendingJoinHandler(pendingJoinService, s.store, s.logger)

			// 初始化 handlers（使用 Service 层）
			networkHandler := handler.NewNetworkHandler(networkService, meshSeedService, s.store, s.logger)
			deviceHandler := handler.NewDeviceHandler(deviceService, s.logger)
			adminHandler := handler.NewAdminHandler(userService, s.logger)
			dashboardHandler := handler.NewDashboardHandler(s.store, s.logger)
			policyHandler := handler.NewPolicyHandler(policyService, s.logger)
			settingsHandler := handler.NewSettingsHandler(settingsService, s.logger)
			wsHandler := handler.NewWSHandler(s.ctrClient, s.store, s.logger)

			ddnsService, err := service.NewDDNSService(s.store.DB())
			if err != nil {
				s.logger.Error("初始化 DDNSService 失败", zap.Error(err))
				return fmt.Errorf("初始化 DDNSService 失败：%w", err)
			}
			// 启动后台自动同步协程
			go ddnsService.StartAutoSync(context.Background())

			ddnsHandler := handler.NewDDNSHandler(ddnsService)

			// ✅ 新增：DDNS Usage Handler
			ddnsUsageHandler := handler.NewDDNSUsageHandler(s.store.DB(), s.logger)

			// ✅ 新增：IP 检测 API
			ddnsDetectHandler := handler.NewIPDetectHandler()

			// 管理员管理
			protected.GET("/admin/profile", adminHandler.GetProfile)
			protected.PUT("/admin/profile", adminHandler.UpdateProfile)
			protected.POST("/admin/change-password", adminHandler.ChangePassword)

			// ✅ 系统备份恢复
			backupHandler := corehandler.NewBackupHandler(s.store.DB(), s.logger)
			protected.POST("/system/backup", backupHandler.CreateBackup)
			protected.GET("/system/backups", backupHandler.ListBackups)
			protected.POST("/system/restore", backupHandler.RestoreBackup)
			protected.DELETE("/system/backup", backupHandler.DeleteBackup)
			protected.GET("/system/backup/download", backupHandler.DownloadBackup)

			// ✅ 系统更新检查
			updateHandler := corehandler.NewUpdateHandler(s.config.App.Version)
			protected.GET("/system/update/check", func(c *gin.Context) {
				resp, err := updateHandler.CheckUpdate()
				if err != nil {
					c.JSON(http.StatusInternalServerError, gin.H{
						"error": "检查更新失败",
					})
					return
				}
				c.JSON(http.StatusOK, gin.H{
					"data": resp,
				})
			})

			// ✅ WebSocket 实时通知推送
			notificationSvc := service.NewNotificationService(s.store.DB(), s.logger)
			notificationHandler := corehandler.NewNotificationHandler(notificationSvc, s.logger, s.store.DB())
			protected.GET("/notifications", notificationHandler.GetNotifications)
			protected.GET("/notifications/unread-count", notificationHandler.GetUnreadCount)
			protected.POST("/notifications/:id/read", notificationHandler.MarkAsRead)
			protected.POST("/notifications/read-all", notificationHandler.MarkAllAsRead)
			protected.DELETE("/notifications/:id", notificationHandler.DeleteNotification)
			protected.POST("/notifications/test", notificationHandler.TestSendNotification)

			// DDNS 配置
			protected.GET("/ddns/config", ddnsHandler.GetDDNSConfig)
			protected.PUT("/ddns/config", ddnsHandler.UpdateDDNSConfig)
			protected.POST("/ddns/test", ddnsHandler.TestDDNSConnectivity)
			protected.POST("/ddns/sync", ddnsHandler.SyncDDNS)

			// ✅ IP 检测 API（用于前端自动填充）
			protected.GET("/ddns/detect-ip", ddnsDetectHandler.DetectIP)

			// ✅ DDNS 统计 API（用于 Dashboard 监控）
			ddnsStatsHandler := handler.NewDDNSStatsHandler(s.store.DB())
			protected.GET("/ddns/stats", ddnsStatsHandler.GetDDNSStats)

			// ✅ DDNS Usage 管理
			protected.POST("/ddns/usages", ddnsUsageHandler.CreateUsage)
			protected.GET("/ddns/usages/available", ddnsUsageHandler.GetAvailableUsages)
			protected.GET("/ddns/check-prefix", ddnsUsageHandler.CheckPrefixOccupied)

			// Dashboard
			protected.GET("/dashboard/stats", dashboardHandler.GetStats)
			protected.GET("/dashboard/logs", dashboardHandler.GetRecentLogs)
			protected.GET("/dashboard/system-info", dashboardHandler.GetSystemInfo)
			protected.GET("/dashboard/link-distribution", dashboardHandler.GetLinkDistribution)
			protected.POST("/dashboard/logs/clear", dashboardHandler.ClearLogs) // 新增：清理日志

			// 系统设置
			protected.GET("/settings", settingsHandler.GetSettings)
			protected.PUT("/settings", settingsHandler.UpdateSettings)

			// 系统配置（WG 模式等）
			protected.GET("/system-config/wg-mode", systemConfigHandler.GetWGMode)
			protected.PUT("/system-config/wg-mode", systemConfigHandler.SetWGMode)

			// 系统运维（P1/P2 功能）- 使用 SystemConfigHandler 统一管理
			protected.POST("/system/change-password", systemConfigHandler.ChangePassword) // P1: 修改密码
			protected.POST("/system/restart-core", systemConfigHandler.RestartCore)       // P1: 重启核心

			// 组网管理
			protected.GET("/networks", networkHandler.ListNetworks)
			protected.POST("/networks", networkHandler.CreateNetwork)
			protected.POST("/networks/preview", networkHandler.PreviewMeshSeed)
			protected.POST("/networks/join", networkHandler.JoinNetwork)
			protected.GET("/networks/:id", networkHandler.GetNetwork)
			protected.PUT("/networks/:id", networkHandler.UpdateNetwork)
			protected.DELETE("/networks/:id", networkHandler.DeleteNetwork)
			protected.POST("/networks/:id/start", networkHandler.StartNetwork)
			protected.POST("/networks/:id/stop", networkHandler.StopNetwork)
			protected.POST("/networks/:id/switch-mode", networkHandler.SwitchMode)
			protected.POST("/networks/:id/meshseed", networkHandler.GenerateMeshSeed)

			// 设备管理（使用独立前缀避免路由冲突）
			protected.GET("/devices", deviceHandler.ListDevices)
			protected.POST("/devices", deviceHandler.CreateDevice)
			protected.GET("/devices/:id", deviceHandler.GetDevice)
			protected.PUT("/devices/:id", deviceHandler.UpdateDevice)
			protected.DELETE("/devices/:id", deviceHandler.DeleteDevice)
			protected.GET("/devices/:id/config", deviceHandler.GenerateDeviceConfig)

			// 策略管理
			protected.GET("/policies", policyHandler.ListPolicies)
			protected.POST("/policies", policyHandler.CreatePolicy)
			protected.GET("/policies/:id", policyHandler.GetPolicy)
			protected.PUT("/policies/:id", policyHandler.UpdatePolicy)
			protected.DELETE("/policies/:id", policyHandler.DeletePolicy)

			// ExternalService 管理（用户视角）
			protected.GET("/services", serviceHandler.ListServices)
			protected.POST("/services", serviceHandler.CreateService)
			protected.GET("/services/:id", serviceHandler.GetService)
			protected.PUT("/services/:id", serviceHandler.UpdateService)
			protected.DELETE("/services/:id", serviceHandler.DeleteService)
			protected.POST("/services/:id/test", serviceHandler.TestServiceConnectivity)
			protected.GET("/services/schema", serviceHandler.GetServiceSchema)

			protected.GET("/monitor/metrics", s.handleMetrics)

			// 注册 WebSocket 通道
			protected.GET("/ws", wsHandler.ServeWS)

			// 待审核管理
			protected.GET("/pending-joins", pendingJoinHandler.ListPendingJoins)
			protected.POST("/pending-joins/:id/approve", pendingJoinHandler.ApproveJoin)
			protected.POST("/pending-joins/:id/reject", pendingJoinHandler.RejectJoin)
			protected.GET("/pending-joins/count", pendingJoinHandler.CountPending)
			protected.POST("/pending-joins/cleanup", pendingJoinHandler.DeleteExpired)
		}
	}

	return nil
}

// handleMetrics 监控指标 API
func (s *Server) handleMetrics(c *gin.Context) {
	// 获取系统信息
	var memStats runtime.MemStats
	runtime.ReadMemStats(&memStats)

	// 获取 CPU 使用率（简化版本）
	cpuPercent := 0.0
	if cpus, err := cpu.Percent(time.Second, false); err == nil && len(cpus) > 0 {
		cpuPercent = cpus[0]
	}

	// 网络统计（从数据库）
	var deviceCount, networkCount, onlineCount int64
	s.store.DB().Model(&model.Device{}).Count(&deviceCount)
	s.store.DB().Model(&model.Network{}).Count(&networkCount)
	s.store.DB().Model(&model.Device{}).Where("status = ?", "online").Count(&onlineCount)

	// 返回 Prometheus 格式或 JSON 格式
	accept := c.GetHeader("Accept")
	if strings.Contains(accept, "text/plain") {
		// Prometheus 格式
		metrics := fmt.Sprintf(`# HELP meshray_memory_alloc_bytes 当前内存使用量
# TYPE meshray_memory_alloc_bytes gauge
meshray_memory_alloc_bytes %d

# HELP meshray_cpu_usage_percent CPU 使用率
# TYPE meshray_cpu_usage_percent gauge
meshray_cpu_usage_percent %.2f

# HELP meshray_device_total 设备总数
# TYPE meshray_device_total gauge
meshray_device_total %d

# HELP meshray_device_online 在线设备数
# TYPE meshray_device_online gauge
meshray_device_online %d

# HELP meshray_network_total 网络总数
# TYPE meshray_network_total gauge
meshray_network_total %d
`,
			memStats.Alloc,
			cpuPercent,
			deviceCount,
			onlineCount,
			networkCount)

		c.Header("Content-Type", "text/plain; version=0.0.4")
		c.String(200, metrics)
	} else {
		// JSON 格式（前端使用）
		c.JSON(200, gin.H{
			"data": gin.H{
				"memory": gin.H{
					"alloc_bytes": memStats.Alloc,
					"alloc_mb":    float64(memStats.Alloc) / 1024 / 1024,
					"sys_bytes":   memStats.Sys,
					"num_gc":      memStats.NumGC,
				},
				"cpu": gin.H{
					"usage_percent": cpuPercent,
				},
				"devices": gin.H{
					"total":   deviceCount,
					"online":  onlineCount,
					"offline": deviceCount - onlineCount,
				},
				"networks": gin.H{
					"total": networkCount,
				},
				"timestamp": time.Now().Unix(),
			},
		})
	}
}

// getContentType 根据文件扩展名返回 Content-Type
func getContentType(filePath string) string {
	ext := strings.ToLower(filepath.Ext(filePath))
	switch ext {
	case ".html":
		return "text/html; charset=utf-8"
	case ".css":
		return "text/css; charset=utf-8"
	case ".js":
		return "application/javascript; charset=utf-8"
	case ".json":
		return "application/json; charset=utf-8"
	case ".png":
		return "image/png"
	case ".jpg", ".jpeg":
		return "image/jpeg"
	case ".gif":
		return "image/gif"
	case ".svg":
		return "image/svg+xml"
	case ".ico":
		return "image/x-icon"
	default:
		return "application/octet-stream"
	}
}

// Run 启动 API 服务器
func (s *Server) Run() error {
	addr := fmt.Sprintf(":%d", s.config.Server.Port)
	s.logger.Info("Starting MeshRay", zap.String("address", addr))

	// 打印访问地址
	fmt.Println("")
	fmt.Printf("🌐 MeshRay 启动成功！\n")
	fmt.Printf("📍 访问地址：http://localhost:%d\n", s.config.Server.Port)
	fmt.Printf("💡 提示：请在浏览器中打开上述地址访问管理面板\n")
	fmt.Println("")

	return s.engine.Run(addr)
}

// loadSigningKey 加载或生成 Ed25519 签名密钥
func (s *Server) loadSigningKey() (ed25519.PrivateKey, error) {
	var key model.SecurityKey
	err := s.store.DB().Where("name = ?", "meshseed_signing").First(&key).Error

	if err == nil {
		// 从数据库加载已有密钥
		keyBytes, decodeErr := base64.StdEncoding.DecodeString(key.Value)
		if decodeErr != nil {
			return nil, fmt.Errorf("解码密钥失败：%w", decodeErr)
		}
		return ed25519.PrivateKey(keyBytes), nil
	}

	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, fmt.Errorf("查询密钥失败：%w", err)
	}

	// 密钥不存在，生成新密钥并保存
	_, newKey, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		return nil, fmt.Errorf("生成密钥失败：%w", err)
	}

	keyBytes := []byte(newKey)
	err = s.store.DB().Create(&model.SecurityKey{
		Name:      "meshseed_signing",
		Value:     base64.StdEncoding.EncodeToString(keyBytes),
		Algorithm: "ed25519",
		Purpose:   "MeshSeed 数字签名",
	}).Error
	if err != nil {
		return nil, fmt.Errorf("保存密钥失败：%w", err)
	}

	s.logger.Info("已生成新的签名密钥")
	return newKey, nil
}
