package grpc

import (
	"context"
	"errors"
	"strconv"
	"sync"
	api "test3k/authDB/pkg/api"
	"time"
	// kafka "github.com/segmentio/kafka-go"
)

type user struct {
	ID        int32
	Code      string
	Login     string
	Password  string
	Email     string
	Confirmed bool
}

type gRPCServer struct {
	mu    sync.Mutex
	users map[string]*user
	api.UnimplementedAuthDBServer
	id int32
}

func NewServer() *gRPCServer {
	return &gRPCServer{
		mu:    sync.Mutex{},
		users: make(map[string]*user),
		id:    0,
	}
}

func (s *gRPCServer) Login(ctx context.Context, req *api.LoginRequest) (*api.LoginResponse, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	//
	user, ok := s.users[req.GetLogin()]
	if !ok {
		return nil, errors.New("login unknown")
	}

	//
	if !user.Confirmed {
		return nil, errors.New("login unconfirmed")
	}

	//
	if user.Password != req.Password {
		return nil, errors.New("password incorrect")
	}

	return &api.LoginResponse{
		ID: user.ID,
	}, nil
}

func (s *gRPCServer) Registration(ctx context.Context, req *api.RegistrationRequest) (*api.RegistrationResponse, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	//
	_, ok := s.users[req.GetLogin()]
	if ok {
		return nil, errors.New("login already registered")
	}

	//
	s.id = s.id + 1

	//
	id := time.Now().Nanosecond()
	code := strconv.Itoa(id / 2)

	//
	s.users[req.Login] = &user{
		ID:        s.id,
		Code:      code,
		Login:     req.Login,
		Password:  strconv.Itoa(id),
		Email:     req.Email,
		Confirmed: false,
	}

	// //
	// consumer := kafka.NewReader(kafka.ReaderConfig{
	// 	Brokers:   []string{"localhost:9092"},
	// 	Topic:     "topic-A",
	// 	Partition: 0,
	// 	MinBytes:  10e3, // 10KB
	// 	MaxBytes:  10e6, // 10MB
	// })
	// defer consumer.Close()

	// //
	// // consumer.SetOffset(42)

	// //
	// for {
	// 	m, err := consumer.ReadMessage(ctx)
	// 	if err != nil {
	// 		log.Fatal(err)
	// 	}

	// 	fmt.Printf("message at offset %d: %s = %s\n", m.Offset, string(m.Key), string(m.Value))
	// }

	return &api.RegistrationResponse{
		Code:  code,
		Email: req.Email,
	}, nil
}

func (s *gRPCServer) Confirmation(ctx context.Context, req *api.ConfirmationRequest) (*api.ConfirmationResponse, error) {
	s.mu.Lock()
	defer s.mu.Unlock()

	//
	for _, x := range s.users {
		if x.Code == req.GetCode() {
			if x.Confirmed {
				return nil, errors.New("already confirmed")
			}

			//
			x.Confirmed = true

			return &api.ConfirmationResponse{
				ID: x.ID,
			}, nil
		}
	}

	return nil, errors.New("code unknown")
}