// service/auth_service.go
package service

import (
	"errors"

	"api_bb/internal/models"
	"api_bb/internal/repository"
	"api_bb/pkg/logger"

	"go.uber.org/zap"
	"golang.org/x/crypto/bcrypt"
)

type AuthService interface {
	Register(user *models.User) error
	Login(email, password string) (*models.User, string, error)
}

type authService struct {
	userRepo   repository.UserRepository
	jwtService JWTService
	logger     logger.LoggerInterface
}

func NewAuthService(userRepo repository.UserRepository, jwtService JWTService, log logger.LoggerInterface) AuthService {
	// Создаем логгер с контекстом для сервиса
	serviceLogger := log.With(zap.String("service", "auth"))

	return &authService{
		userRepo:   userRepo,
		jwtService: jwtService,
		logger:     serviceLogger,
	}
}

func (s *authService) Register(user *models.User) error {
	s.logger.Info("Registering new user",
		zap.String("email", user.Email),
	)

	existingUser, err := s.userRepo.FindByEmail(user.Email)
	if err == nil && existingUser != nil {
		s.logger.Warn("Registration failed - email already exists",
			zap.String("email", user.Email),
		)
		return errors.New("user with this email already exists")
	}

	err = s.userRepo.Create(user)
	if err != nil {
		s.logger.Error("Failed to create user in database",
			zap.String("email", user.Email),
			zap.Error(err),
		)
		return err
	}
	

	s.logger.Info("User registered successfully",
		zap.Uint("user_id", user.ID),
		zap.String("email", user.Email),
	)


	return nil
}

func (s *authService) Login(email, password string) (*models.User, string, error) {
	s.logger.Info("Login attempt",
		zap.String("email", email),
		zap.Int("password_length", len(password)),
	)

	user, err := s.userRepo.FindByEmail(email)
	if err != nil {
		s.logger.Warn("Login failed - user not found",
			zap.String("email", email),
			zap.Error(err),
		)
		return nil, "", errors.New("invalid email")
	}

	s.logger.Debug("User found for login",
		zap.Uint("user_id", user.ID),
		zap.String("stored_hash_prefix", user.Password[:min(10, len(user.Password))]),
	)

	// Проверяем пароль
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		s.logger.Warn("Login failed - invalid password",
			zap.Uint("user_id", user.ID),
			zap.String("email", email),
			zap.Error(err),
		)
		return nil, "", errors.New("invalid password")
	}

	s.logger.Info("Login successful",
		zap.Uint("user_id", user.ID),
		zap.String("email", email),
	)

	token, err := s.jwtService.GenerateToken(user.ID, user.Email)
	if err != nil {
		s.logger.Error("Failed to generate JWT token",
			zap.Uint("user_id", user.ID),
			zap.Error(err),
		)
		return nil, "", err
	}

	return user, token, nil
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
