package auth

import (
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/service/auth"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/logger"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"github.com/break/junhong_cmp_fiber/pkg/response"
	"github.com/go-playground/validator/v10"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
)

// Handler 统一认证处理器
// 合并后台和 H5 认证接口
type Handler struct {
	authService *auth.Service
	validator   *validator.Validate
}

// NewHandler 创建统一认证处理器
func NewHandler(authService *auth.Service, validator *validator.Validate) *Handler {
	return &Handler{
		authService: authService,
		validator:   validator,
	}
}

// Login 统一登录（后台+H5）
// POST /api/auth/login - 统一登录（后台+H5）
func (h *Handler) Login(c *fiber.Ctx) error {
	var req dto.LoginRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	clientIP := c.IP()
	ctx := c.UserContext()

	resp, err := h.authService.Login(ctx, &req, clientIP)
	if err != nil {
		return err
	}

	return response.Success(c, resp)
}

// Logout 统一登出
// POST /api/auth/logout - 统一登出
func (h *Handler) Logout(c *fiber.Ctx) error {
	authorization := c.Get("Authorization")
	accessToken := ""
	if len(authorization) > 7 && authorization[:7] == "Bearer " {
		accessToken = authorization[7:]
	}

	// 尝试从请求体获取 refresh_token（可选）
	refreshToken := ""
	var req dto.RefreshTokenRequest
	if err := c.BodyParser(&req); err == nil {
		refreshToken = req.RefreshToken
	}

	ctx := c.UserContext()

	if err := h.authService.Logout(ctx, accessToken, refreshToken); err != nil {
		return err
	}

	return response.Success(c, nil)
}

// RefreshToken 刷新 Token
// POST /api/auth/refresh-token - 刷新 Token
func (h *Handler) RefreshToken(c *fiber.Ctx) error {
	var req dto.RefreshTokenRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	ctx := c.UserContext()

	newAccessToken, err := h.authService.RefreshToken(ctx, req.RefreshToken)
	if err != nil {
		return err
	}

	resp := &dto.RefreshTokenResponse{
		AccessToken: newAccessToken,
		ExpiresIn:   86400,
	}

	return response.Success(c, resp)
}

// GetMe 获取用户信息
// GET /api/auth/me - 获取用户信息
func (h *Handler) GetMe(c *fiber.Ctx) error {
	userID := middleware.GetUserIDFromContext(c.UserContext())
	if userID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	ctx := c.UserContext()

	userInfo, permissions, err := h.authService.GetCurrentUser(ctx, userID)
	if err != nil {
		return err
	}

	data := map[string]interface{}{
		"user":        userInfo,
		"permissions": permissions,
	}

	return response.Success(c, data)
}

// ChangePassword 修改密码
// PUT /api/auth/password - 修改密码
func (h *Handler) ChangePassword(c *fiber.Ctx) error {
	userID := middleware.GetUserIDFromContext(c.UserContext())
	if userID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	var req dto.ChangePasswordRequest
	if err := c.BodyParser(&req); err != nil {
		return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
	}

	if err := h.validator.Struct(&req); err != nil {
		logger.GetAppLogger().Warn("参数验证失败",
			zap.String("path", c.Path()),
			zap.String("method", c.Method()),
			zap.Error(err),
		)
		return errors.New(errors.CodeInvalidParam)
	}

	ctx := c.UserContext()

	if err := h.authService.ChangePassword(ctx, userID, req.OldPassword, req.NewPassword); err != nil {
		return err
	}

	return response.Success(c, nil)
}
