package auth

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/passwords"
)

const authPasswordMinLength = 6

// ProfileHandler owns the authenticated user's profile routes.
type ProfileHandler struct {
	store                Store
	passwordAuthDisabled bool
}

func passwordTooShortMessage(minLength int) string {
	return fmt.Sprintf("Password must be at least %d characters", minLength)
}

// Me handles GET /api/v1/me.
// Returns the authenticated user's profile information.
func (handler *ProfileHandler) Me(r api.AuthenticatedRequest) (api.Response, error) {
	return api.OK(userResponseFromDomain(r.User.User)), nil
}

// UpdateMe handles PATCH /api/v1/me.
// Updates the authenticated user's display name, avatar, or password.
func (handler *ProfileHandler) UpdateMe(r api.AuthenticatedJSON[dto.UpdateProfileRequest]) (api.Response, error) {

	request := r.Body

	passwordChangeRequested := request.CurrentPassword != nil || request.NewPassword != nil
	var nextPasswordHash string
	if passwordChangeRequested {
		if handler.passwordAuthDisabled {
			return api.Response{}, api.NewHTTPError(http.StatusServiceUnavailable, "Password auth is disabled")
		}
		if request.CurrentPassword == nil || request.NewPassword == nil {
			return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "currentPassword and newPassword are required")
		}
		currentPassword := strings.TrimSpace(*request.CurrentPassword)
		newPassword := strings.TrimSpace(*request.NewPassword)
		if currentPassword == "" || newPassword == "" {
			return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "currentPassword and newPassword are required")
		}
		if len(newPassword) < authPasswordMinLength {
			return api.Response{}, api.NewHTTPError(http.StatusBadRequest, passwordTooShortMessage(authPasswordMinLength))
		}
		passwordHash, err := handler.store.LoadUserPasswordHash(r.Context(), r.UserID())
		if err != nil {
			return api.Response{}, err
		}
		passwordOK, err := passwords.Verify(currentPassword, passwordHash)
		if err != nil {
			return api.Response{}, err
		}
		if !passwordOK {
			return api.Response{}, api.NewHTTPError(http.StatusUnauthorized, "Invalid current password")
		}
		nextHash, err := passwords.Hash(newPassword)
		if err != nil {
			return api.Response{}, err
		}
		nextPasswordHash = nextHash
	}

	updatedUser := r.User.User

	if request.DisplayName != nil {
		user, err := handler.store.UpdateUserDisplayName(r.Context(), r.UserID(), *request.DisplayName)
		if err != nil {
			return api.Response{}, err
		}
		updatedUser = user
	}

	if request.AvatarURL != nil {
		user, err := handler.store.UpdateUserAvatarURL(r.Context(), r.UserID(), *request.AvatarURL)
		if err != nil {
			return api.Response{}, err
		}
		updatedUser = user
	}

	if passwordChangeRequested {
		user, err := handler.store.UpdateUserPasswordHash(r.Context(), r.UserID(), nextPasswordHash)
		if err != nil {
			return api.Response{}, err
		}
		updatedUser = user
	}

	return api.OK(userResponseFromDomain(updatedUser)), nil
}
