package routes

import (
	"bssapp-backend/auth"
	"bssapp-backend/internal/security"
	"bssapp-backend/repository"
	"database/sql"
	"encoding/json"
	"net/http"
	"time"
)

func setRefreshCookie(w http.ResponseWriter, plain string, exp time.Time) {
	http.SetCookie(w, &http.Cookie{
		Name:     "mk_refresh",
		Value:    plain,
		Path:     "/",
		Expires:  exp,
		HttpOnly: true,
		SameSite: http.SameSiteLaxMode,
		Secure:   false, // prod: true
	})
}

func AuthRefreshHandler(db *sql.DB) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {

		w.Header().Set("Content-Type", "application/json; charset=utf-8")

		// 1) refresh cookie
		c, err := r.Cookie("mk_refresh")
		if err != nil || c.Value == "" {
			http.Error(w, "refresh token missing", http.StatusUnauthorized)
			return
		}

		hash := security.HashRefreshToken(c.Value)
		rtRepo := repository.NewRefreshTokenRepository(db)

		// 2) validate + consume
		mkUserID, err := rtRepo.ConsumeValid(hash)
		if err != nil {
			http.Error(w, "refresh token invalid", http.StatusUnauthorized)
			return
		}

		// 3) rotate
		newPlain, newHash, err := security.GenerateRefreshToken()
		if err != nil {
			http.Error(w, "refresh gen failed", http.StatusInternalServerError)
			return
		}
		refreshExp := time.Now().Add(14 * 24 * time.Hour)
		if err := rtRepo.IssueRefreshToken(mkUserID, newHash, refreshExp); err != nil {
			http.Error(w, "refresh store failed", http.StatusInternalServerError)
			return
		}
		setRefreshCookie(w, newPlain, refreshExp)

		// 4) mk user reload
		mkRepo := repository.NewMkUserRepository(db)
		mkUser, err := mkRepo.GetByID(mkUserID)
		if err != nil || !mkUser.IsActive {
			http.Error(w, "user invalid", http.StatusUnauthorized)
			return
		}
		if mkUser.ForcePasswordChange {
			http.Error(w, "password change required", http.StatusForbidden)
			return
		}

		// 5) new access token
		claims := auth.BuildClaimsFromUser(mkUser, 15*time.Minute)

		token, err := auth.GenerateToken(
			claims,
			mkUser.Username,
			mkUser.ForcePasswordChange,
		)
		if err != nil {
			http.Error(w, "access token gen failed", http.StatusInternalServerError)
			return
		}

		// 6) response
		_ = json.NewEncoder(w).Encode(map[string]any{
			"success": true,
			"token":   token,
		})

	}
}
