package repository

import (
	"database/sql"
	"errors"
	"time"
)

var ErrRefreshTokenInvalid = errors.New("refresh token invalid")

type RefreshTokenRepository struct {
	DB *sql.DB
}

func NewRefreshTokenRepository(db *sql.DB) *RefreshTokenRepository {
	return &RefreshTokenRepository{DB: db}
}

// Yeni refresh (HASH saklanır)
func (r *RefreshTokenRepository) IssueRefreshToken(
	mkUserID int64,
	tokenHash string,
	expiresAt time.Time,
) error {
	_, err := r.DB.Exec(`
		INSERT INTO mk_refresh_tokens (mk_user_id, token_hash, expires_at)
		VALUES ($1,$2,$3)
	`, mkUserID, tokenHash, expiresAt)
	return err
}

// Tek refresh’i revoke et (rotation / logout)
func (r *RefreshTokenRepository) RevokeByHash(hash string) error {
	_, err := r.DB.Exec(`
		UPDATE mk_refresh_tokens
		SET revoked_at = now()
		WHERE token_hash = $1
		  AND revoked_at IS NULL
	`, hash)
	return err
}

// Kullanıcının tüm refresh’lerini revoke et (logout-all / password change)
func (r *RefreshTokenRepository) RevokeAllForUser(mkUserID int64) error {
	_, err := r.DB.Exec(`
		UPDATE mk_refresh_tokens
		SET revoked_at = now()
		WHERE mk_user_id = $1
		  AND revoked_at IS NULL
	`, mkUserID)
	return err
}

// Geçerli refresh’i tüket (validate + rotate)
func (r *RefreshTokenRepository) ConsumeValid(tokenHash string) (int64, error) {
	var mkUserID int64
	err := r.DB.QueryRow(`
		SELECT mk_user_id
		FROM mk_refresh_tokens
		WHERE token_hash = $1
		  AND revoked_at IS NULL
		  AND expires_at > now()
	`, tokenHash).Scan(&mkUserID)

	if err != nil {
		if err == sql.ErrNoRows {
			return 0, ErrRefreshTokenInvalid
		}
		return 0, err
	}

	// tek kullanımlık: eskiyi revoke et
	_, _ = r.DB.Exec(`
		UPDATE mk_refresh_tokens
		SET revoked_at = now()
		WHERE token_hash = $1
	`, tokenHash)

	return mkUserID, nil
}
