package handlers

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"software-download-center/database"
	"software-download-center/models"
	"software-download-center/utils"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// LogEntry 日志条目
type LogEntry struct {
	Time    string `json:"time"`
	Level   string `json:"level"`
	Message string `json:"message"`
}

var logBuffer []LogEntry
var maxLogEntries = 1000

// AddLog 添加日志到缓冲区
func AddLog(level, message string) {
	entry := LogEntry{
		Time:    time.Now().Format("2006-01-02 15:04:05"),
		Level:   level,
		Message: message,
	}
	
	logBuffer = append(logBuffer, entry)
	
	// 同时输出到控制台（使用 utils.Logger）
	logger := utils.NewLogger()
	switch level {
	case "ERROR":
		logger.Error(message)
	case "WARN":
		logger.Warn(message)
	case "INFO":
		logger.Info(message)
	default:
		logger.System(message)
	}
	
	// 保持缓冲区大小
	if len(logBuffer) > maxLogEntries {
		logBuffer = logBuffer[len(logBuffer)-maxLogEntries:]
	}
}

// GetLogBuffer 获取日志缓冲区（用于外部访问）
func GetLogBuffer() []LogEntry {
	return logBuffer
}

// GetLogs 获取日志
func GetLogs(c *gin.Context) {
	limit := 100
	if limitStr := c.Query("limit"); limitStr != "" {
		fmt.Sscanf(limitStr, "%d", &limit)
	}

	start := len(logBuffer) - limit
	if start < 0 {
		start = 0
	}

	logs := logBuffer[start:]
	c.JSON(http.StatusOK, gin.H{
		"logs": logs,
		"total": len(logBuffer),
	})
}

// GetRoutes 获取所有路由
func GetRoutes(c *gin.Context) {
	var routes []models.Route
	if err := database.DB.Order("`order` ASC, id ASC").Find(&routes).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "获取路由失败",
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"routes": routes,
	})
}

// CreateRoute 创建路由
func CreateRoute(c *gin.Context) {
	var route models.Route
	if err := c.ShouldBindJSON(&route); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数错误: " + err.Error(),
		})
		return
	}

	// 验证路径是否已存在
	var existingRoute models.Route
	if err := database.DB.Where("path = ? AND method = ?", route.Path, route.Method).First(&existingRoute).Error; err == nil {
		AddLog("WARN", fmt.Sprintf("创建路由失败（已存在）: %s %s (IP: %s)", route.Method, route.Path, c.ClientIP()))
		c.JSON(http.StatusConflict, gin.H{
			"error": "路由已存在",
		})
		return
	}

	if err := database.DB.Create(&route).Error; err != nil {
		AddLog("ERROR", fmt.Sprintf("创建路由数据库错误: %s %s - %s (IP: %s)", route.Method, route.Path, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "创建路由失败",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("创建路由成功: %s %s (类型: %s, IP: %s)", route.Method, route.Path, route.Type, c.ClientIP()))
	c.JSON(http.StatusOK, gin.H{
		"message": "路由创建成功",
		"route":   route,
	})
}

// UpdateRoute 更新路由
func UpdateRoute(c *gin.Context) {
	id := c.Param("id")
	var route models.Route
	oldPath := route.Path
	oldMethod := route.Method

	if err := database.DB.First(&route, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			AddLog("WARN", fmt.Sprintf("更新路由失败（不存在）: ID=%s (IP: %s)", id, c.ClientIP()))
			c.JSON(http.StatusNotFound, gin.H{
				"error": "路由不存在",
			})
			return
		}
		AddLog("ERROR", fmt.Sprintf("查询路由失败: ID=%s - %s (IP: %s)", id, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "查询路由失败",
		})
		return
	}

	oldPath = route.Path
	oldMethod = route.Method

	if err := c.ShouldBindJSON(&route); err != nil {
		AddLog("WARN", fmt.Sprintf("更新路由请求参数错误: ID=%s - %s (IP: %s)", id, err.Error(), c.ClientIP()))
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数错误",
		})
		return
	}

	if err := database.DB.Save(&route).Error; err != nil {
		AddLog("ERROR", fmt.Sprintf("更新路由数据库错误: %s %s - %s (IP: %s)", route.Method, route.Path, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "更新路由失败",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("更新路由成功: %s %s -> %s %s (IP: %s)", oldMethod, oldPath, route.Method, route.Path, c.ClientIP()))
	c.JSON(http.StatusOK, gin.H{
		"message": "路由更新成功",
		"route":   route,
	})
}

// DeleteRoute 删除路由
func DeleteRoute(c *gin.Context) {
	id := c.Param("id")
	var route models.Route
	if err := database.DB.First(&route, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			AddLog("WARN", fmt.Sprintf("删除路由失败（不存在）: ID=%s (IP: %s)", id, c.ClientIP()))
			c.JSON(http.StatusNotFound, gin.H{
				"error": "路由不存在",
			})
			return
		}
		AddLog("ERROR", fmt.Sprintf("查询路由失败: ID=%s - %s (IP: %s)", id, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "查询路由失败",
		})
		return
	}

	routeInfo := fmt.Sprintf("%s %s", route.Method, route.Path)

	if err := database.DB.Delete(&route).Error; err != nil {
		AddLog("ERROR", fmt.Sprintf("删除路由数据库错误: %s - %s (IP: %s)", routeInfo, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "删除路由失败",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("删除路由成功: %s (IP: %s)", routeInfo, c.ClientIP()))
	c.JSON(http.StatusOK, gin.H{
		"message": "路由删除成功",
	})
}

// GetFiles 获取文件列表
func GetFiles(c *gin.Context) {
	dir := c.Query("dir")
	if dir == "" {
		dir = "public/downloads"
	}

	// 安全检查：防止目录遍历
	if strings.Contains(dir, "..") {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "无效的目录路径",
		})
		return
	}

	files, err := os.ReadDir(dir)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "读取目录失败",
		})
		return
	}

	var fileList []gin.H
	for _, file := range files {
		info, _ := file.Info()
		fileList = append(fileList, gin.H{
			"name":    file.Name(),
			"size":    info.Size(),
			"mod_time": info.ModTime().Format("2006-01-02 15:04:05"),
			"is_dir":  file.IsDir(),
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"files": fileList,
		"path":  dir,
	})
}

// SaveFile 保存文件
func SaveFile(c *gin.Context) {
	var req struct {
		Path    string `json:"path" binding:"required"`
		Content string `json:"content" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数错误",
		})
		return
	}

	// 安全检查
	if strings.Contains(req.Path, "..") {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "无效的文件路径",
		})
		return
	}

	// 确保目录存在
	dir := filepath.Dir(req.Path)
	if err := os.MkdirAll(dir, 0755); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "创建目录失败",
		})
		return
	}

	// 保存文件
	if err := os.WriteFile(req.Path, []byte(req.Content), 0644); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "保存文件失败",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("保存文件: %s", req.Path))
	c.JSON(http.StatusOK, gin.H{
		"message": "文件保存成功",
	})
}

// ReadFile 读取文件
func ReadFile(c *gin.Context) {
	path := c.Query("path")
	if path == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "缺少文件路径参数",
		})
		return
	}

	// 安全检查
	if strings.Contains(path, "..") {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "无效的文件路径",
		})
		return
	}

	content, err := os.ReadFile(path)
	if err != nil {
		AddLog("ERROR", fmt.Sprintf("读取文件失败: %s - %s (IP: %s)", path, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "读取文件失败",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("读取文件: %s (大小: %d 字节, IP: %s)", path, len(content), c.ClientIP()))
	c.JSON(http.StatusOK, gin.H{
		"content": string(content),
		"path":    path,
		"size":    len(content),
	})
}

// ReloadRoutes 热重载路由和配置
func ReloadRoutes(c *gin.Context) {
	var req struct {
		Type string `json:"type"` // "config" 或 "all"
	}
	
	if err := c.ShouldBindJSON(&req); err != nil {
		req.Type = "all"
	}
	
	if req.Type == "config" || req.Type == "all" {
		// 重新加载所有配置文件
		files := []string{"tool-status.json", "update-info.json", "media-types.json"}
		successCount := 0
		for _, file := range files {
			if _, err := os.Stat(filepath.Join("public", file)); err == nil {
				if err := utils.ReloadConfig(file); err == nil {
					successCount++
				}
			}
		}
		AddLog("INFO", fmt.Sprintf("重新加载配置文件: %d/%d 成功 (IP: %s)", successCount, len(files), c.ClientIP()))
	}
	
	// 注意：Gin 不支持动态路由重载，路由更改需要重启服务器
	if req.Type == "routes" || req.Type == "all" {
		AddLog("INFO", fmt.Sprintf("路由热重载请求（需要重启服务器才能生效）(IP: %s)", c.ClientIP()))
		c.JSON(http.StatusOK, gin.H{
			"message": "配置已重新加载",
			"note":    "路由更改需要重启服务器才能生效，建议使用进程管理器（如 systemd、supervisor）",
		})
		return
	}
	
	c.JSON(http.StatusOK, gin.H{
		"message": "配置已重新加载",
	})
}

// GetSystemInfo 获取系统信息
func GetSystemInfo(c *gin.Context) {
	var userCount int64
	var routeCount int64
	database.DB.Model(&models.User{}).Count(&userCount)
	database.DB.Model(&models.Route{}).Count(&routeCount)

	c.JSON(http.StatusOK, gin.H{
		"users":      userCount,
		"routes":    routeCount,
		"logs":       len(logBuffer),
		"version":    "1.0.0",
		"server_time": time.Now().Format("2006-01-02 15:04:05"),
	})
}

// UpdateJSONConfig 更新 JSON 配置文件
func UpdateJSONConfig(c *gin.Context) {
	var req struct {
		File    string                 `json:"file" binding:"required"`
		Content map[string]interface{} `json:"content" binding:"required"`
		Reload  bool                   `json:"reload"` // 是否立即重新加载
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数错误",
		})
		return
	}

	// 验证文件路径
	allowedFiles := []string{"tool-status.json", "update-info.json", "media-types.json"}
	allowed := false
	for _, f := range allowedFiles {
		if req.File == f {
			allowed = true
			break
		}
	}

	if !allowed {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "不允许修改此文件",
		})
		return
	}

	// 使用配置工具保存并更新缓存
	if err := utils.SaveConfig(req.File, req.Content); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "保存文件失败: " + err.Error(),
		})
		return
	}

	message := "配置文件更新成功"
	if req.Reload {
		// 重新加载配置到缓存
		if err := utils.ReloadConfig(req.File); err != nil {
			AddLog("WARN", fmt.Sprintf("配置文件已保存但重新加载失败: %s - %s", req.File, err.Error()))
			message = "配置文件已保存，但重新加载时出现警告"
		} else {
			AddLog("INFO", fmt.Sprintf("配置文件已保存并立即加载: %s", req.File))
			message = "配置文件已保存并立即生效"
		}
	} else {
		AddLog("INFO", fmt.Sprintf("更新配置文件: %s", req.File))
	}

	c.JSON(http.StatusOK, gin.H{
		"message": message,
		"file":    req.File,
	})
}
