package handlers

import (
	"errors"
	"net/url"
	"strings"
)

type loginRequest struct {
	Account    string `json:"account"`
	Password   string `json:"password"`
	ClientID   string `json:"clientId"`
	ClientName string `json:"clientName"`
}

type verifyRequest struct {
	Token string `json:"token"`
}

type registerRequest struct {
	Account    string `json:"account"`
	Password   string `json:"password"`
	Username   string `json:"username"`
	Email      string `json:"email"`
	InviteCode string `json:"inviteCode"`
}

type verifyEmailRequest struct {
	Account string `json:"account"`
	Code    string `json:"code"`
}

type updateProfileRequest struct {
	Password   *string `json:"password"`
	Username   *string `json:"username"`
	Phone      *string `json:"phone"`
	AvatarURL  *string `json:"avatarUrl"`
	WebsiteURL *string `json:"websiteUrl"`
	Bio        *string `json:"bio"`
}

type forgotPasswordRequest struct {
	Account string `json:"account"`
	Email   string `json:"email"`
}

type resetPasswordRequest struct {
	Account     string `json:"account"`
	Code        string `json:"code"`
	NewPassword string `json:"newPassword"`
}

type secondaryEmailRequest struct {
	Email string `json:"email"`
}

type verifySecondaryEmailRequest struct {
	Email string `json:"email"`
	Code  string `json:"code"`
}

type updateCheckInConfigRequest struct {
	RewardCoins int `json:"rewardCoins"`
}

type updateRegistrationPolicyRequest struct {
	RequireInviteCode bool `json:"requireInviteCode"`
}

type createInviteRequest struct {
	Note      string `json:"note"`
	MaxUses   int    `json:"maxUses"`
	ExpiresAt string `json:"expiresAt"`
}

type createUserRequest struct {
	Account         string   `json:"account"`
	Password        string   `json:"password"`
	Username        string   `json:"username"`
	Email           string   `json:"email"`
	Level           int      `json:"level"`
	SproutCoins     int      `json:"sproutCoins"`
	SecondaryEmails []string `json:"secondaryEmails"`
	Phone           string   `json:"phone"`
	AvatarURL       string   `json:"avatarUrl"`
	WebsiteURL      string   `json:"websiteUrl"`
	Bio             string   `json:"bio"`
}

const maxBanReasonLen = 500

type updateUserRequest struct {
	Password        *string   `json:"password"`
	Username        *string   `json:"username"`
	Email           *string   `json:"email"`
	Level           *int      `json:"level"`
	SproutCoins     *int      `json:"sproutCoins"`
	SecondaryEmails *[]string `json:"secondaryEmails"`
	Phone           *string   `json:"phone"`
	AvatarURL       *string   `json:"avatarUrl"`
	WebsiteURL      *string   `json:"websiteUrl"`
	Bio             *string   `json:"bio"`
	Banned          *bool     `json:"banned"`
	BanReason       *string   `json:"banReason"`
}

const maxWebsiteURLLen = 2048

func normalizePublicWebsiteURL(raw string) (string, error) {
	s := strings.TrimSpace(raw)
	if s == "" {
		return "", nil
	}
	if len(s) > maxWebsiteURLLen {
		return "", errors.New("website url is too long")
	}
	lower := strings.ToLower(s)
	if strings.HasPrefix(lower, "javascript:") || strings.HasPrefix(lower, "data:") {
		return "", errors.New("invalid website url")
	}
	candidate := s
	if !strings.Contains(candidate, "://") {
		candidate = "https://" + candidate
	}
	u, err := url.Parse(candidate)
	if err != nil || u.Host == "" {
		return "", errors.New("invalid website url")
	}
	scheme := strings.ToLower(u.Scheme)
	if scheme != "http" && scheme != "https" {
		return "", errors.New("only http and https urls are allowed")
	}
	u.Scheme = scheme
	return u.String(), nil
}
