package api

import (
	"encoding/json"
	"net/http"
	"time"

	"clicd/internal/config"

	"golang.org/x/crypto/bcrypt"
)

type LoginLog struct {
	Time      string `json:"time"`
	Username  string `json:"username"`
	IP        string `json:"ip"`
	UserAgent string `json:"user_agent"`
	Success   bool   `json:"success"`
}

var loginLogs = make([]LoginLog, 0)

// HandleLanguage returns or updates the global panel language.
func HandleLanguage(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: map[string]string{
			"language": config.NormalizeLanguage(config.AppConfig.Language),
		}})
	case http.MethodPost, http.MethodPut:
		var req struct {
			Language string `json:"language"`
		}
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Message: "Invalid request body"})
			return
		}
		config.AppConfig.Language = config.NormalizeLanguage(req.Language)
		if err := config.SaveConfig(); err != nil {
			jsonResponse(w, http.StatusInternalServerError, APIResponse{Success: false, Message: "Failed to save language"})
			return
		}
		jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: map[string]string{
			"language": config.AppConfig.Language,
		}})
	default:
		jsonResponse(w, http.StatusMethodNotAllowed, APIResponse{Success: false, Message: "Method not allowed"})
	}
}

// RecordLoginLog adds a login attempt to the log (persisted to config)
func RecordLoginLog(username, ip, userAgent string, success bool) {
	config.AddLoginLog(username, ip, userAgent, success)

	log := LoginLog{
		Time:      time.Now().UTC().Format("2006-01-02 15:04:05 UTC"),
		Username:  username,
		IP:        ip,
		UserAgent: userAgent,
		Success:   success,
	}
	loginLogs = append(loginLogs, log)
	if len(loginLogs) > 200 {
		loginLogs = loginLogs[len(loginLogs)-200:]
	}
}

// RestoreLoginLogs restores login logs from config
func RestoreLoginLogs() {
	for _, l := range config.AppConfig.LoginLogs {
		loginLogs = append(loginLogs, LoginLog{
			Time:      l.Time,
			Username:  l.Username,
			IP:        l.IP,
			UserAgent: l.UserAgent,
			Success:   l.Success,
		})
	}
}

// HandleLoginLogs returns login history
func HandleLoginLogs(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		jsonResponse(w, http.StatusMethodNotAllowed, APIResponse{Success: false, Message: "Method not allowed"})
		return
	}
	if !requireScope(w, r, "loginlog:read") {
		return
	}

	// Return in reverse (newest first)
	reversed := make([]LoginLog, len(loginLogs))
	for i, l := range loginLogs {
		reversed[len(loginLogs)-1-i] = l
	}
	if reversed == nil {
		reversed = []LoginLog{}
	}

	jsonResponse(w, http.StatusOK, APIResponse{Success: true, Data: reversed})
}

// HandleAdminPasswordChange changes admin password
func HandleAdminPasswordChange(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		jsonResponse(w, http.StatusMethodNotAllowed, APIResponse{Success: false, Message: "Method not allowed"})
		return
	}

	var req struct {
		OldPassword string `json:"old_password"`
		NewPassword string `json:"new_password"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Message: "Invalid request body"})
		return
	}

	if len(req.NewPassword) < 6 {
		jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Message: "新密码至少 6 位"})
		return
	}

	if err := bcrypt.CompareHashAndPassword([]byte(config.AppConfig.AdminPassHash), []byte(req.OldPassword)); err != nil {
		jsonResponse(w, http.StatusUnauthorized, APIResponse{Success: false, Message: "当前密码不正确"})
		return
	}

	hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		jsonResponse(w, http.StatusInternalServerError, APIResponse{Success: false, Message: "密码加密失败"})
		return
	}

	config.AppConfig.AdminPassHash = string(hash)
	if err := config.SaveConfig(); err != nil {
		jsonResponse(w, http.StatusInternalServerError, APIResponse{Success: false, Message: "保存配置失败"})
		return
	}

	jsonResponse(w, http.StatusOK, APIResponse{Success: true, Message: "密码修改成功"})
}

// HandleAdminUsernameChange changes admin username
func HandleAdminUsernameChange(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		jsonResponse(w, http.StatusMethodNotAllowed, APIResponse{Success: false, Message: "Method not allowed"})
		return
	}

	var req struct {
		NewUsername string `json:"new_username"`
		Password    string `json:"password"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Message: "Invalid request body"})
		return
	}

	if len(req.NewUsername) < 3 {
		jsonResponse(w, http.StatusBadRequest, APIResponse{Success: false, Message: "用户名至少 3 位"})
		return
	}

	if err := bcrypt.CompareHashAndPassword([]byte(config.AppConfig.AdminPassHash), []byte(req.Password)); err != nil {
		jsonResponse(w, http.StatusUnauthorized, APIResponse{Success: false, Message: "密码不正确"})
		return
	}

	config.AppConfig.AdminUser = req.NewUsername
	if err := config.SaveConfig(); err != nil {
		jsonResponse(w, http.StatusInternalServerError, APIResponse{Success: false, Message: "保存配置失败"})
		return
	}

	jsonResponse(w, http.StatusOK, APIResponse{Success: true, Message: "用户名修改成功"})
}
