package handlers

import (
	"crypto/rand"
	"crypto/sha256"
	"crypto/subtle"
	"encoding/hex"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"

	"sproutgate-backend/internal/auth"
	"sproutgate-backend/internal/email"
	"sproutgate-backend/internal/models"
	"sproutgate-backend/internal/storage"
)

type Handler struct {
	store *storage.Store
}

func NewHandler(store *storage.Store) *Handler {
	return &Handler{store: store}
}

type loginRequest struct {
	Account  string `json:"account"`
	Password string `json:"password"`
}

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"`
}

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"`
	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 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"`
	Bio             string   `json:"bio"`
}

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"`
	Bio             *string   `json:"bio"`
}

func (h *Handler) Login(c *gin.Context) {
	var req loginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	req.Account = strings.TrimSpace(req.Account)
	if req.Account == "" || req.Password == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account and password are required"})
		return
	}
	user, found, err := h.store.GetUser(req.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"})
		return
	}
	if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"})
		return
	}
	token, expiresAt, err := auth.GenerateToken(h.store.JWTSecret(), h.store.JWTIssuer(), user.Account, 7*24*time.Hour)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate token"})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"token":     token,
		"expiresAt": expiresAt.Format(time.RFC3339),
		"user":      user.Public(),
	})
}

func (h *Handler) Verify(c *gin.Context) {
	var req verifyRequest
	if err := c.ShouldBindJSON(&req); err != nil || strings.TrimSpace(req.Token) == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "token is required"})
		return
	}
	claims, err := auth.ParseToken(h.store.JWTSecret(), h.store.JWTIssuer(), req.Token)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"valid": false, "error": "invalid token"})
		return
	}
	user, found, err := h.store.GetUser(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusUnauthorized, gin.H{"valid": false, "error": "user not found"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"valid": true, "user": user.Public()})
}

func (h *Handler) Register(c *gin.Context) {
	var req registerRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	req.Account = strings.TrimSpace(req.Account)
	req.Email = strings.TrimSpace(req.Email)
	if req.Account == "" || strings.TrimSpace(req.Password) == "" || req.Email == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account, password and email are required"})
		return
	}
	if _, found, err := h.store.GetUser(req.Account); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	} else if found {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account already exists"})
		return
	}

	code, err := generateVerificationCode()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate code"})
		return
	}
	hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to hash password"})
		return
	}
	expiresAt := time.Now().Add(10 * time.Minute)
	pending := models.PendingUser{
		Account:      req.Account,
		PasswordHash: string(hash),
		Username:     req.Username,
		Email:        req.Email,
		CodeHash:     hashCode(code),
		CreatedAt:    models.NowISO(),
		ExpiresAt:    expiresAt.Format(time.RFC3339),
	}
	if err := h.store.SavePending(pending); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save pending user"})
		return
	}
	if err := email.SendVerificationEmail(h.store.EmailConfig(), req.Email, code, 10*time.Minute); err != nil {
		_ = h.store.DeletePending(req.Account)
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to send email: %v", err)})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"sent":      true,
		"expiresAt": expiresAt.Format(time.RFC3339),
	})
}

func (h *Handler) VerifyEmail(c *gin.Context) {
	var req verifyEmailRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	req.Account = strings.TrimSpace(req.Account)
	req.Code = strings.TrimSpace(req.Code)
	if req.Account == "" || req.Code == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account and code are required"})
		return
	}
	pending, found, err := h.store.GetPending(req.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load pending user"})
		return
	}
	if !found {
		c.JSON(http.StatusBadRequest, gin.H{"error": "pending registration not found"})
		return
	}
	expiresAt, err := time.Parse(time.RFC3339, pending.ExpiresAt)
	if err != nil || time.Now().After(expiresAt) {
		_ = h.store.DeletePending(req.Account)
		c.JSON(http.StatusBadRequest, gin.H{"error": "verification code expired"})
		return
	}
	if !verifyCode(req.Code, pending.CodeHash) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid verification code"})
		return
	}
	record := models.UserRecord{
		Account:      pending.Account,
		PasswordHash: pending.PasswordHash,
		Username:     pending.Username,
		Email:        pending.Email,
		Level:        0,
		SproutCoins:  0,
		SecondaryEmails: []string{},
		CreatedAt:    models.NowISO(),
		UpdatedAt:    models.NowISO(),
	}
	if err := h.store.CreateUser(record); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	_ = h.store.DeletePending(req.Account)
	c.JSON(http.StatusCreated, gin.H{"created": true, "user": record.Public()})
}

func (h *Handler) ForgotPassword(c *gin.Context) {
	var req forgotPasswordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	req.Account = strings.TrimSpace(req.Account)
	req.Email = strings.TrimSpace(req.Email)
	if req.Account == "" || req.Email == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account and email are required"})
		return
	}
	user, found, err := h.store.GetUser(req.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found || strings.TrimSpace(user.Email) == "" || user.Email != req.Email {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account or email not matched"})
		return
	}
	code, err := generateVerificationCode()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate code"})
		return
	}
	expiresAt := time.Now().Add(10 * time.Minute)
	resetRecord := models.ResetPassword{
		Account:   user.Account,
		Email:     user.Email,
		CodeHash:  hashCode(code),
		CreatedAt: models.NowISO(),
		ExpiresAt: expiresAt.Format(time.RFC3339),
	}
	if err := h.store.SaveReset(resetRecord); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save reset token"})
		return
	}
	if err := email.SendResetPasswordEmail(h.store.EmailConfig(), user.Email, code, 10*time.Minute); err != nil {
		_ = h.store.DeleteReset(user.Account)
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to send email: %v", err)})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"sent":      true,
		"expiresAt": expiresAt.Format(time.RFC3339),
	})
}

func (h *Handler) ResetPassword(c *gin.Context) {
	var req resetPasswordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	req.Account = strings.TrimSpace(req.Account)
	req.Code = strings.TrimSpace(req.Code)
	if req.Account == "" || req.Code == "" || strings.TrimSpace(req.NewPassword) == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account, code and newPassword are required"})
		return
	}
	resetRecord, found, err := h.store.GetReset(req.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load reset token"})
		return
	}
	if !found {
		c.JSON(http.StatusBadRequest, gin.H{"error": "reset request not found"})
		return
	}
	expiresAt, err := time.Parse(time.RFC3339, resetRecord.ExpiresAt)
	if err != nil || time.Now().After(expiresAt) {
		_ = h.store.DeleteReset(req.Account)
		c.JSON(http.StatusBadRequest, gin.H{"error": "reset code expired"})
		return
	}
	if !verifyCode(req.Code, resetRecord.CodeHash) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid reset code"})
		return
	}
	user, found, err := h.store.GetUser(req.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusBadRequest, gin.H{"error": "user not found"})
		return
	}
	hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to hash password"})
		return
	}
	user.PasswordHash = string(hash)
	if err := h.store.SaveUser(user); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save user"})
		return
	}
	_ = h.store.DeleteReset(req.Account)
	c.JSON(http.StatusOK, gin.H{"reset": true})
}

func (h *Handler) RequestSecondaryEmail(c *gin.Context) {
	token := bearerToken(c.GetHeader("Authorization"))
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
		return
	}
	claims, err := auth.ParseToken(h.store.JWTSecret(), h.store.JWTIssuer(), token)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
		return
	}
	var req secondaryEmailRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	emailAddr := strings.TrimSpace(req.Email)
	if emailAddr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "email is required"})
		return
	}
	user, found, err := h.store.GetUser(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
		return
	}
	if strings.TrimSpace(user.Email) == emailAddr {
		c.JSON(http.StatusBadRequest, gin.H{"error": "email already used as primary"})
		return
	}
	for _, e := range user.SecondaryEmails {
		if e == emailAddr {
			c.JSON(http.StatusBadRequest, gin.H{"error": "email already verified"})
			return
		}
	}
	code, err := generateVerificationCode()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate code"})
		return
	}
	expiresAt := time.Now().Add(10 * time.Minute)
	record := models.SecondaryEmailVerification{
		Account:   user.Account,
		Email:     emailAddr,
		CodeHash:  hashCode(code),
		CreatedAt: models.NowISO(),
		ExpiresAt: expiresAt.Format(time.RFC3339),
	}
	if err := h.store.SaveSecondaryVerification(record); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save verification"})
		return
	}
	if err := email.SendVerificationEmail(h.store.EmailConfig(), emailAddr, code, 10*time.Minute); err != nil {
		_ = h.store.DeleteSecondaryVerification(user.Account, emailAddr)
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to send email: %v", err)})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"sent":      true,
		"expiresAt": expiresAt.Format(time.RFC3339),
	})
}

func (h *Handler) VerifySecondaryEmail(c *gin.Context) {
	token := bearerToken(c.GetHeader("Authorization"))
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
		return
	}
	claims, err := auth.ParseToken(h.store.JWTSecret(), h.store.JWTIssuer(), token)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
		return
	}
	var req verifySecondaryEmailRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	emailAddr := strings.TrimSpace(req.Email)
	code := strings.TrimSpace(req.Code)
	if emailAddr == "" || code == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "email and code are required"})
		return
	}
	record, found, err := h.store.GetSecondaryVerification(claims.Account, emailAddr)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load verification"})
		return
	}
	if !found {
		c.JSON(http.StatusBadRequest, gin.H{"error": "verification not found"})
		return
	}
	expiresAt, err := time.Parse(time.RFC3339, record.ExpiresAt)
	if err != nil || time.Now().After(expiresAt) {
		_ = h.store.DeleteSecondaryVerification(claims.Account, emailAddr)
		c.JSON(http.StatusBadRequest, gin.H{"error": "verification code expired"})
		return
	}
	if !verifyCode(code, record.CodeHash) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid verification code"})
		return
	}
	user, found, err := h.store.GetUser(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
		return
	}
	for _, e := range user.SecondaryEmails {
		if e == emailAddr {
			_ = h.store.DeleteSecondaryVerification(claims.Account, emailAddr)
			c.JSON(http.StatusOK, gin.H{"verified": true, "user": user.Public()})
			return
		}
	}
	user.SecondaryEmails = append(user.SecondaryEmails, emailAddr)
	if err := h.store.SaveUser(user); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save user"})
		return
	}
	_ = h.store.DeleteSecondaryVerification(claims.Account, emailAddr)
	c.JSON(http.StatusOK, gin.H{"verified": true, "user": user.Public()})
}

func (h *Handler) Me(c *gin.Context) {
	token := bearerToken(c.GetHeader("Authorization"))
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
		return
	}
	claims, err := auth.ParseToken(h.store.JWTSecret(), h.store.JWTIssuer(), token)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
		return
	}
	user, found, err := h.store.GetUser(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"user": user.Public()})
}

func (h *Handler) UpdateProfile(c *gin.Context) {
	token := bearerToken(c.GetHeader("Authorization"))
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
		return
	}
	claims, err := auth.ParseToken(h.store.JWTSecret(), h.store.JWTIssuer(), token)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
		return
	}
	var req updateProfileRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	user, found, err := h.store.GetUser(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
		return
	}
	if req.Password != nil && strings.TrimSpace(*req.Password) != "" {
		hash, err := bcrypt.GenerateFromPassword([]byte(*req.Password), bcrypt.DefaultCost)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to hash password"})
			return
		}
		user.PasswordHash = string(hash)
	}
	if req.Username != nil {
		user.Username = *req.Username
	}
	if req.Phone != nil {
		user.Phone = *req.Phone
	}
	if req.AvatarURL != nil {
		user.AvatarURL = *req.AvatarURL
	}
	if req.Bio != nil {
		user.Bio = *req.Bio
	}
	if err := h.store.SaveUser(user); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save user"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"user": user.Public()})
}

func (h *Handler) ListUsers(c *gin.Context) {
	users, err := h.store.ListUsers()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load users"})
		return
	}
	publicUsers := make([]models.UserPublic, 0, len(users))
	for _, u := range users {
		publicUsers = append(publicUsers, u.Public())
	}
	c.JSON(http.StatusOK, gin.H{"total": len(publicUsers), "users": publicUsers})
}

func (h *Handler) CreateUser(c *gin.Context) {
	var req createUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	req.Account = strings.TrimSpace(req.Account)
	if req.Account == "" || strings.TrimSpace(req.Password) == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account and password are required"})
		return
	}
	hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to hash password"})
		return
	}
	record := models.UserRecord{
		Account:      req.Account,
		PasswordHash: string(hash),
		Username:     req.Username,
		Email:        req.Email,
		Level:        req.Level,
		SproutCoins:  req.SproutCoins,
		SecondaryEmails: req.SecondaryEmails,
		Phone:        req.Phone,
		AvatarURL:    req.AvatarURL,
		Bio:          req.Bio,
		CreatedAt:    models.NowISO(),
		UpdatedAt:    models.NowISO(),
	}
	if err := h.store.CreateUser(record); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, gin.H{"user": record.Public()})
}

func (h *Handler) UpdateUser(c *gin.Context) {
	account := strings.TrimSpace(c.Param("account"))
	if account == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account is required"})
		return
	}
	var req updateUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	user, found, err := h.store.GetUser(account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !found {
		c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
		return
	}
	if req.Password != nil && strings.TrimSpace(*req.Password) != "" {
		hash, err := bcrypt.GenerateFromPassword([]byte(*req.Password), bcrypt.DefaultCost)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to hash password"})
			return
		}
		user.PasswordHash = string(hash)
	}
	if req.Username != nil {
		user.Username = *req.Username
	}
	if req.Email != nil {
		user.Email = *req.Email
	}
	if req.Level != nil {
		user.Level = *req.Level
	}
	if req.SproutCoins != nil {
		user.SproutCoins = *req.SproutCoins
	}
	if req.SecondaryEmails != nil {
		user.SecondaryEmails = *req.SecondaryEmails
	}
	if req.Phone != nil {
		user.Phone = *req.Phone
	}
	if req.AvatarURL != nil {
		user.AvatarURL = *req.AvatarURL
	}
	if req.Bio != nil {
		user.Bio = *req.Bio
	}
	if err := h.store.SaveUser(user); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save user"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"user": user.Public()})
}

func (h *Handler) DeleteUser(c *gin.Context) {
	account := strings.TrimSpace(c.Param("account"))
	if account == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "account is required"})
		return
	}
	if err := h.store.DeleteUser(account); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete user"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"deleted": true})
}

func (h *Handler) AdminMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := adminTokenFromRequest(c)
		if token == "" || token != h.store.AdminToken() {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid admin token"})
			c.Abort()
			return
		}
		c.Next()
	}
}

func adminTokenFromRequest(c *gin.Context) string {
	if token := strings.TrimSpace(c.Query("token")); token != "" {
		return token
	}
	if token := strings.TrimSpace(c.GetHeader("X-Admin-Token")); token != "" {
		return token
	}
	authHeader := strings.TrimSpace(c.GetHeader("Authorization"))
	return bearerToken(authHeader)
}

func bearerToken(header string) string {
	if header == "" {
		return ""
	}
	if strings.HasPrefix(strings.ToLower(header), "bearer ") {
		return strings.TrimSpace(header[7:])
	}
	return ""
}

func generateVerificationCode() (string, error) {
	randomBytes := make([]byte, 3)
	if _, err := rand.Read(randomBytes); err != nil {
		return "", err
	}
	number := int(randomBytes[0])<<16 | int(randomBytes[1])<<8 | int(randomBytes[2])
	return fmt.Sprintf("%06d", number%1000000), nil
}

func hashCode(code string) string {
	sum := sha256.Sum256([]byte(code))
	return hex.EncodeToString(sum[:])
}

func verifyCode(code string, hash string) bool {
	return subtle.ConstantTimeCompare([]byte(hashCode(code)), []byte(hash)) == 1
}
