package handler

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"github.com/user-management-system/internal/service"
)

// SMSHandler handles SMS requests
type SMSHandler struct {
	authService    *service.AuthService
	smsCodeService *service.SMSCodeService
}

// SMSLoginRequest 短信登录请求
type SMSLoginRequest struct {
	Phone         string `json:"phone" binding:"required"`
	Code          string `json:"code" binding:"required"`
	DeviceID      string `json:"device_id"`
	DeviceName    string `json:"device_name"`
	DeviceBrowser string `json:"device_browser"`
	DeviceOS      string `json:"device_os"`
}

// NewSMSHandler creates a SMSHandler backed by AuthService + SMSCodeService.
// If both services are nil, the handler will return 503 for all requests.
func NewSMSHandler(authService *service.AuthService, smsCodeService *service.SMSCodeService) *SMSHandler {
	return &SMSHandler{
		authService:    authService,
		smsCodeService: smsCodeService,
	}
}

// SendCode 发送短信验证码
// @Summary 发送短信验证码
// @Description 向指定手机号发送短信验证码（用于注册或登录）
// @Tags 短信验证
// @Accept json
// @Produce json
// @Param request body service.SendCodeRequest true "发送验证码请求"
// @Success 200 {object} Response "发送成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 503 {object} Response "短信服务未配置"
// @Router /api/v1/sms/send [post]
func (h *SMSHandler) SendCode(c *gin.Context) {
	if h.smsCodeService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"code": 503, "message": "SMS service not configured"})
		return
	}

	var req service.SendCodeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
		return
	}

	resp, err := h.smsCodeService.SendCode(c.Request.Context(), &req)
	if err != nil {
		handleError(c, err)
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data":    resp,
	})
}

// LoginByCode 短信验证码登录
// @Summary 短信验证码登录
// @Description 使用手机号和短信验证码登录（带设备信息以支持设备信任链路）
// @Tags 短信验证
// @Accept json
// @Produce json
// @Param request body SMSLoginRequest true "登录请求"
// @Success 200 {object} Response "登录成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 401 {object} Response "验证码错误"
// @Failure 503 {object} Response "短信登录未配置"
// @Router /api/v1/sms/login [post]
func (h *SMSHandler) LoginByCode(c *gin.Context) {
	if h.authService == nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{"code": 503, "message": "SMS login not configured"})
		return
	}

	var req SMSLoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
		return
	}

	clientIP := c.ClientIP()
	resp, err := h.authService.LoginByCode(c.Request.Context(), req.Phone, req.Code, clientIP)
	if err != nil {
		handleError(c, err)
		return
	}

	// 自动注册/更新设备记录（不阻塞主流程）
	// 注意：必须用独立的 background context，不能用 c.Request.Context()（gin 回收后会取消）
	if req.DeviceID != "" && resp != nil && resp.User != nil {
		loginReq := &service.LoginRequest{
			DeviceID:      req.DeviceID,
			DeviceName:    req.DeviceName,
			DeviceBrowser: req.DeviceBrowser,
			DeviceOS:      req.DeviceOS,
		}
		userID := resp.User.ID
		go func() {
			devCtx, cancel := newBackgroundCtx(5)
			defer cancel()
			h.authService.BestEffortRegisterDevicePublic(devCtx, userID, loginReq)
		}()
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data":    resp,
	})
}
