package handlers

import (
	"net/http"

	"cmr-backend/internal/apperr"
	"cmr-backend/internal/httpapi/middleware"
	"cmr-backend/internal/httpx"
	"cmr-backend/internal/service"
)

type AuthHandler struct {
	authService *service.AuthService
}

func NewAuthHandler(authService *service.AuthService) *AuthHandler {
	return &AuthHandler{authService: authService}
}

func (h *AuthHandler) SendSMSCode(w http.ResponseWriter, r *http.Request) {
	var req service.SendSMSCodeInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body"))
		return
	}

	result, err := h.authService.SendSMSCode(r.Context(), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}

	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AuthHandler) LoginSMS(w http.ResponseWriter, r *http.Request) {
	var req service.LoginSMSInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body"))
		return
	}

	result, err := h.authService.LoginSMS(r.Context(), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}

	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AuthHandler) LoginWechatMini(w http.ResponseWriter, r *http.Request) {
	var req service.LoginWechatMiniInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body"))
		return
	}

	result, err := h.authService.LoginWechatMini(r.Context(), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}

	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AuthHandler) BindMobile(w http.ResponseWriter, r *http.Request) {
	var req service.BindMobileInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body"))
		return
	}

	auth := middleware.GetAuthContext(r.Context())
	if auth == nil {
		httpx.WriteError(w, apperr.New(http.StatusUnauthorized, "unauthorized", "missing auth context"))
		return
	}
	req.UserID = auth.UserID

	result, err := h.authService.BindMobile(r.Context(), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}

	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request) {
	var req service.RefreshTokenInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body"))
		return
	}

	result, err := h.authService.Refresh(r.Context(), req)
	if err != nil {
		httpx.WriteError(w, err)
		return
	}

	httpx.WriteJSON(w, http.StatusOK, map[string]any{"data": result})
}

func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) {
	var req service.LogoutInput
	if err := httpx.DecodeJSON(r, &req); err != nil {
		httpx.WriteError(w, apperr.New(http.StatusBadRequest, "invalid_json", "invalid request body"))
		return
	}

	auth := middleware.GetAuthContext(r.Context())
	if auth != nil && req.UserID == "" {
		req.UserID = auth.UserID
	}

	if err := h.authService.Logout(r.Context(), req); err != nil {
		httpx.WriteError(w, err)
		return
	}

	httpx.WriteJSON(w, http.StatusOK, map[string]any{
		"data": map[string]any{
			"loggedOut": true,
		},
	})
}
