package handler

import (
	"net/http"
	"time"
	"github.com/gin-gonic/gin"
)

// AuthHandler 认证处理器骨架
type AuthHandler struct {
	authService    *AuthService
	rsaService     *RSAService
}

// GetPublicKey 获取 RSA 公钥
// GET /api/auth/rsa/public-key
func (h *AuthHandler) GetPublicKey(c *gin.Context) {
	publicKey, err := h.rsaService.GetCurrentPublicKey()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取公钥失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"public_key": publicKey})
}

// Login 用户登录
// POST /api/auth/login
// Body: {"username": "xxx", "encrypted_password": "RSA加密后的密码"}
func (h *AuthHandler) Login(c *gin.Context) {
	var req LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	// 1. RSA 解密密码
	password, err := h.rsaService.Decrypt(req.EncryptedPassword)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "密码解密失败", "code": "AUTH_005"})
		return
	}

	// 2. 验证用户名密码
	user, err := h.authService.ValidateCredentials(req.Username, password)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误", "code": "AUTH_001"})
		return
	}

	// 3. 检查用户状态
	if user.Status != "active" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "账户未激活或已禁用", "code": "AUTH_003"})
		return
	}

	// 4. 检查账户有效期
	if user.AccountExpiresAt != nil && user.AccountExpiresAt.Before(time.Now()) {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "账户已过期", "code": "AUTH_007"})
		return
	}

	// 5. 检查密码是否已过期
	if user.PasswordExpiresAt != nil && user.PasswordExpiresAt.Before(time.Now()) {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "密码已过期，请联系管理员重置", "code": "AUTH_006"})
		return
	}

	// 6. 生成 JWT
	token, err := h.authService.GenerateJWT(user)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "生成Token失败"})
		return
	}

	// 7. 构建响应（含附加标识）
	resp := LoginResponse{Token: token, User: user.ToDTO()}
	
	// 首次登录需强制改密
	if user.MustChangePassword {
		resp.MustChangePassword = true
	}
	
	// 密码7天内过期提醒
	if user.PasswordExpiresAt != nil {
		days := int(time.Until(*user.PasswordExpiresAt).Hours() / 24)
		if days <= 7 && days > 0 {
			resp.PasswordExpireDays = days
		}
	}
	
	// 账户7天内过期提醒
	if user.AccountExpiresAt != nil {
		days := int(time.Until(*user.AccountExpiresAt).Hours() / 24)
		if days <= 7 && days > 0 {
			resp.AccountExpireDays = days
		}
	}

	// 更新最后登录时间
	h.authService.UpdateLastLogin(user.ID)

	c.JSON(http.StatusOK, resp)
}

// ForceChangePassword 首次登录强制改密
// PUT /api/user/password/force-change
func (h *AuthHandler) ForceChangePassword(c *gin.Context) {
	userID := c.GetInt64("user_id")
	
	var req ForceChangePasswordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误"})
		return
	}

	// 修改密码并更新相关标识
	err := h.authService.ForceChangePassword(userID, req.NewPassword)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "修改密码失败"})
		return
	}

	// 密码修改成功后：
	// 1. password_expires_at = now + 90天
	// 2. must_change_password = false

	c.JSON(http.StatusOK, gin.H{"message": "密码修改成功"})
}

type LoginRequest struct {
	Username          string `json:"username" binding:"required"`
	EncryptedPassword string `json:"encrypted_password" binding:"required"`
}

type LoginResponse struct {
	Token              string  `json:"token"`
	User               UserDTO `json:"user"`
	MustChangePassword bool    `json:"must_change_password,omitempty"` // 需强制改密
	PasswordExpireDays int     `json:"password_expire_days,omitempty"` // 密码剩余天数
	AccountExpireDays  int     `json:"account_expire_days,omitempty"`  // 账户剩余天数
}

type ForceChangePasswordRequest struct {
	NewPassword string `json:"new_password" binding:"required,min=8"`
}
