package auth

import (
	"context"
	"errors"

	"git.kocoder.xyz/kocoded/szuntis-backend/repository"
	"github.com/google/uuid"
	"golang.org/x/crypto/bcrypt"
)

type authRepository struct {
	users    map[string]repository.User //map[LoginName]User
	sessions map[uuid.UUID]string       //map[sessionToken]email
}

func NewMemeoryAuthRepository() repository.AuthRepository {
	return &authRepository{
		users:    map[string]repository.User{},
		sessions: map[uuid.UUID]string{},
	}
}

func (a *authRepository) GetUserByToken(ctx context.Context, userId uuid.UUID) (repository.User, error) {
	ln, ok := a.sessions[userId]
	if !ok {
		return repository.User{}, errors.New("you have to be logged in to do that")
	}

	u, ok := a.users[ln]
	if !ok {
		return repository.User{}, errors.New("you have to be logged in to do that")
	}
	return u, nil
}

func (a *authRepository) Login(ctx context.Context, loginParams *repository.LoginParams) (uuid.UUID, error) {
	u, ok := a.users[loginParams.LoginName]
	if !ok {
		return uuid.Nil, errors.New("couldn't log user in")
	}

	if err := bcrypt.CompareHashAndPassword(u.Password, []byte(loginParams.Password)); err != nil {
		return uuid.Nil, errors.New("couldn't log user in")
	}

	sessionToken, err := uuid.NewUUID()
	if err != nil {
		return uuid.Nil, errors.New("couldn't log user in")
	}
	a.sessions[sessionToken] = loginParams.LoginName

	return sessionToken, nil
}

func (a *authRepository) Register(ctx context.Context, registerParams *repository.RegisterParams) (bool, error) {
	if _, ok := a.users[registerParams.LoginName]; ok {
		return false, errors.New("couldn't register user")
	}

	res, err := bcrypt.GenerateFromPassword([]byte(registerParams.Password), 7)
	if err != nil {
		return false, errors.New("couldn't register user")
	}

	u := repository.User{
		Username:     registerParams.Username,
		FirstName:    registerParams.FirstName,
		LastName:     registerParams.LastName,
		LoginName:    registerParams.LoginName,
		EmailAddress: registerParams.EmailAddress,
		Password:     res,
	}

	a.users[registerParams.LoginName] = u

	return true, nil
}
