package auth

import (
	"time"

	"gitea.local/admin/hspguard/internal/cache"
	"gitea.local/admin/hspguard/internal/config"
	imiddleware "gitea.local/admin/hspguard/internal/middleware"
	"gitea.local/admin/hspguard/internal/repository"
	"gitea.local/admin/hspguard/internal/types"
	"gitea.local/admin/hspguard/internal/util"
	"github.com/go-chi/chi/v5"
	"github.com/golang-jwt/jwt/v5"
)

type AuthHandler struct {
	repo  *repository.Queries
	cache *cache.Client
	cfg   *config.AppConfig
}

func (h *AuthHandler) signTokens(user *repository.User) (string, string, error) {
	accessClaims := types.UserClaims{
		UserEmail: user.Email,
		IsAdmin:   user.IsAdmin,
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:    h.cfg.Uri,
			Subject:   user.ID.String(),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
		},
	}

	accessToken, err := util.SignJwtToken(accessClaims, h.cfg.Jwt.PrivateKey)
	if err != nil {
		return "", "", err
	}

	refreshClaims := types.UserClaims{
		UserEmail: user.Email,
		IsAdmin:   user.IsAdmin,
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:    h.cfg.Uri,
			Subject:   user.ID.String(),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * 24 * time.Hour)),
		},
	}

	refreshToken, err := util.SignJwtToken(refreshClaims, h.cfg.Jwt.PrivateKey)
	if err != nil {
		return "", "", err
	}

	return accessToken, refreshToken, nil
}

func NewAuthHandler(repo *repository.Queries, cache *cache.Client, cfg *config.AppConfig) *AuthHandler {
	return &AuthHandler{
		repo,
		cache,
		cfg,
	}
}

func (h *AuthHandler) RegisterRoutes(api chi.Router) {
	api.Route("/auth", func(r chi.Router) {
		r.Group(func(protected chi.Router) {
			authMiddleware := imiddleware.NewAuthMiddleware(h.cfg)
			protected.Use(authMiddleware.Runner)

			protected.Get("/profile", h.getProfile)
			protected.Post("/email", h.requestEmailOtp)
			protected.Post("/email/otp", h.confirmOtp)
			protected.Post("/verify", h.finishVerification)
		})

		r.Post("/login", h.login)
		r.Post("/refresh", h.refreshToken)
	})
}
