package auth

import (
	"system-altrak/internal/domain"

	"gorm.io/gorm"
)

type AuthRepository interface {
	GetUserByUsername(username string) (*domain.User, error)
	GetUserByID(id uint) (*domain.User, error)
	SaveRefreshToken(token *domain.RefreshToken) error
	GetRefreshToken(hash string) (*domain.RefreshToken, error)
	RevokeRefreshToken(userID uint) error
	WithTransaction(fn func(repo AuthRepository) error) error
}

type repositoryImpl struct {
	db *gorm.DB
}

func NewRepository(db *gorm.DB) AuthRepository {
	return &repositoryImpl{db: db}
}

func (r *repositoryImpl) GetUserByUsername(username string) (*domain.User, error) {
	var user domain.User
	err := r.db.Where("LOWER(username) = LOWER(?)", username).First(&user).Error
	return &user, err
}

func (r *repositoryImpl) GetUserByID(id uint) (*domain.User, error) {
	var user domain.User
	err := r.db.First(&user, id).Error
	return &user, err
}

func (r *repositoryImpl) SaveRefreshToken(token *domain.RefreshToken) error {
	return r.db.Create(token).Error
}

func (r *repositoryImpl) GetRefreshToken(hash string) (*domain.RefreshToken, error) {
	var rt domain.RefreshToken
	err := r.db.Where("token_hash = ? AND revoked = ?", hash, false).First(&rt).Error
	return &rt, err
}

func (r *repositoryImpl) RevokeRefreshToken(userID uint) error {
	return r.db.Model(&domain.RefreshToken{}).Where("user_id = ?", userID).Update("revoked", true).Error
}

func (r *repositoryImpl) WithTransaction(fn func(repo AuthRepository) error) error {
	return r.db.Transaction(func(tx *gorm.DB) error {
		return fn(&repositoryImpl{db: tx})
	})
}
