package service

import (
	"context"
	"time"

	"erp-mvp/core-service/internal/auth"
	"erp-mvp/core-service/internal/models"
	"erp-mvp/core-service/internal/repository"

	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
)

type AuthService interface {
	Register(ctx context.Context, req *models.RegisterRequest) (*models.LoginResponse, error)
	Login(ctx context.Context, req *models.LoginRequest) (*models.LoginResponse, error)
}

type authService struct {
	orgRepo    repository.OrganizationRepository
	userRepo   repository.UserRepository
	jwtService *auth.JWTService
	logger     *logrus.Logger
}

func NewAuthService(orgRepo repository.OrganizationRepository, userRepo repository.UserRepository, jwtService *auth.JWTService) AuthService {
	return &authService{
		orgRepo:    orgRepo,
		userRepo:   userRepo,
		jwtService: jwtService,
		logger:     logrus.New(),
	}
}

func (s *authService) Register(ctx context.Context, req *models.RegisterRequest) (*models.LoginResponse, error) {
	s.logger.Info("Starting registration process")

	// Проверяем, что пользователь с таким email не существует
	existingUser, err := s.userRepo.GetByEmail(ctx, req.UserEmail)
	if err == nil && existingUser != nil {
		s.logger.Error("User with this email already exists")
		return nil, &ValidationError{Message: "User with this email already exists"}
	}

	// Создаем организацию
	orgID := uuid.New()
	org := &models.Organization{
		ID:        orgID,
		Name:      req.OrganizationName,
		Type:      req.OrganizationType,
		Settings:  models.JSON{"created_at": time.Now().Unix()},
		CreatedAt: time.Now(),
	}

	s.logger.Info("Creating organization with ID: ", orgID)
	if err := s.orgRepo.Create(ctx, org); err != nil {
		s.logger.Error("Failed to create organization: ", err)
		return nil, err
	}
	s.logger.Info("Organization created successfully")

	// Хешируем пароль
	passwordHash, err := auth.HashPassword(req.UserPassword)
	if err != nil {
		s.logger.Error("Failed to hash password: ", err)
		return nil, err
	}
	s.logger.Info("Password hashed successfully")

	// Создаем пользователя
	userID := uuid.New()
	user := &models.User{
		ID:             userID,
		OrganizationID: orgID,
		Email:          req.UserEmail,
		Role:           "admin", // Первый пользователь становится админом
		CreatedAt:      time.Now(),
	}

	s.logger.Info("Creating user with ID: ", userID)
	if err := s.userRepo.Create(ctx, user, passwordHash); err != nil {
		s.logger.Error("Failed to create user: ", err)
		return nil, err
	}
	s.logger.Info("User created successfully")

	// Генерируем JWT токен
	token, err := s.jwtService.GenerateToken(user.ID, org.ID, user.Email, user.Role)
	if err != nil {
		s.logger.Error("Failed to generate token: ", err)
		return nil, err
	}
	s.logger.Info("JWT token generated successfully")

	return &models.LoginResponse{
		Token: token,
		User: models.UserResponse{
			ID:    user.ID,
			Email: user.Email,
			Role:  user.Role,
		},
		Organization: models.OrganizationResponse{
			ID:   org.ID,
			Name: org.Name,
			Type: org.Type,
		},
	}, nil
}

func (s *authService) Login(ctx context.Context, req *models.LoginRequest) (*models.LoginResponse, error) {
	// Получаем пользователя по email
	user, err := s.userRepo.GetByEmail(ctx, req.Email)
	if err != nil {
		return nil, &ValidationError{Message: "Invalid email or password"}
	}

	// Проверяем пароль
	if !auth.CheckPassword(req.Password, user.PasswordHash) {
		return nil, &ValidationError{Message: "Invalid email or password"}
	}

	// Генерируем JWT токен
	token, err := s.jwtService.GenerateToken(user.ID, user.OrganizationID, user.Email, user.Role)
	if err != nil {
		return nil, err
	}

	// Получаем организацию для ответа
	org, err := s.orgRepo.GetByID(ctx, user.OrganizationID)
	if err != nil {
		return nil, err
	}

	return &models.LoginResponse{
		Token: token,
		User: models.UserResponse{
			ID:    user.ID,
			Email: user.Email,
			Role:  user.Role,
		},
		Organization: models.OrganizationResponse{
			ID:   org.ID,
			Name: org.Name,
			Type: org.Type,
		},
	}, nil
}

// ValidationError ошибка валидации
type ValidationError struct {
	Message string
}

func (e *ValidationError) Error() string {
	return e.Message
}
