package service
/* 
import (
	"errors"
	"fmt"
	"log"
	"rijig/config"
	dto "rijig/dto/auth"
	"rijig/internal/repositories"
	repository "rijig/internal/repositories/auth"
	"rijig/model"
	"rijig/utils"
	"time"

	"github.com/golang-jwt/jwt/v5"
	"golang.org/x/crypto/bcrypt"
)

const (
	ErrEmailTaken            = "email is already used"
	ErrPhoneTaken            = "phone number is already used"
	ErrInvalidPassword       = "password does not match"
	ErrRoleNotFound          = "role not found"
	ErrFailedToGenerateToken = "failed to generate token"
	ErrFailedToHashPassword  = "failed to hash password"
	ErrFailedToCreateUser    = "failed to create user"
	ErrIncorrectPassword     = "incorrect password"
	ErrAccountNotFound       = "account not found"
)

type AuthAdminService interface {
	RegisterAdmin(request *dto.RegisterAdminRequest) (*model.User, error)

	LoginAdmin(req *dto.LoginAdminRequest) (*dto.LoginResponse, error)
	LogoutAdmin(userID, deviceID string) error
}

type authAdminService struct {
	UserRepo  repository.AuthAdminRepository
	RoleRepo  repositories.RoleRepository
	SecretKey string
}

func NewAuthAdminService(userRepo repository.AuthAdminRepository, roleRepo repositories.RoleRepository, secretKey string) AuthAdminService {
	return &authAdminService{UserRepo: userRepo, RoleRepo: roleRepo, SecretKey: secretKey}
}

func (s *authAdminService) RegisterAdmin(request *dto.RegisterAdminRequest) (*model.User, error) {

	if existingUser, _ := s.UserRepo.FindByEmail(request.Email); existingUser != nil {
		return nil, errors.New(ErrEmailTaken)
	}

	if existingUser, _ := s.UserRepo.FindByPhone(request.Phone); existingUser != nil {
		return nil, errors.New(ErrPhoneTaken)
	}

	role, err := s.UserRepo.FindRoleByName("administrator")
	if err != nil {
		return nil, errors.New(ErrRoleNotFound)
	}

	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(request.Password), bcrypt.DefaultCost)
	if err != nil {
		log.Println("Error hashing password:", err)
		return nil, errors.New(ErrFailedToHashPassword)
	}

	user := &model.User{
		Name:         request.Name,
		Email:        request.Email,
		Phone:        request.Phone,
		Password:     string(hashedPassword),
		RoleID:       role.ID,
		Role:         role,
		Dateofbirth:  request.Dateofbirth,
		Placeofbirth: request.Placeofbirth,
		Gender:       request.Gender,
		RegistrationStatus: "completed",
	}

	createdUser, err := s.UserRepo.CreateUser(user)
	if err != nil {
		log.Println("Error creating user:", err)
		return nil, fmt.Errorf("%s: %v", ErrFailedToCreateUser, err)
	}

	return createdUser, nil
}

func (s *authAdminService) LoginAdmin(req *dto.LoginAdminRequest) (*dto.LoginResponse, error) {

	user, err := s.UserRepo.FindByEmail(req.Email)
	if err != nil {
		log.Println("User not found:", err)
		return nil, errors.New(ErrAccountNotFound)
	}

	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
		log.Println("Incorrect password:", err)
		return nil, errors.New(ErrIncorrectPassword)
	}

	existingUser, err := s.UserRepo.FindAdminByEmailandRoleid(req.Email, "42bdecce-f2ad-44ae-b3d6-883c1fbddaf7")
	if err != nil {
		return nil, fmt.Errorf("failed to check existing user: %w", err)
	}

	var adminUser *model.User
	if existingUser != nil {
		adminUser = existingUser
	} else {

		adminUser = &model.User{
			Email:              req.Email,
			RoleID:             "42bdecce-f2ad-44ae-b3d6-883c1fbddaf7",
		}
		createdUser, err := s.UserRepo.CreateUser(adminUser)
		if err != nil {
			return nil, err
		}
		adminUser = createdUser
	}

	token, err := s.generateJWTToken(adminUser.ID, req.Deviceid)
	if err != nil {
		return nil, err
	}

	role, err := s.RoleRepo.FindByID(user.RoleID)
	if err != nil {
		return nil, fmt.Errorf("failed to get role: %w", err)
	}

	deviceID := req.Deviceid
	if err := s.saveSessionAdminData(user.ID, deviceID, user.RoleID, role.RoleName, token); err != nil {
		return nil, err
	}

	return &dto.LoginResponse{
		UserID: user.ID,
		Role:   user.Role.RoleName,
		Token:  token,
	}, nil
}

func (s *authAdminService) saveSessionAdminData(userID string, deviceID string, roleID string, roleName string, token string) error {
	sessionKey := fmt.Sprintf("session:%s:%s", userID, deviceID)
	sessionData := map[string]interface{}{
		"userID":   userID,
		"roleID":   roleID,
		"roleName": roleName,
	}

	if err := utils.SetJSONData(sessionKey, sessionData, 24*time.Hour); err != nil {
		return fmt.Errorf("failed to set session data: %w", err)
	}

	if err := utils.SetStringData("session_token:"+userID+":"+deviceID, token, 24*time.Hour); err != nil {
		return fmt.Errorf("failed to set session token: %w", err)
	}

	return nil
}

func (s *authAdminService) generateJWTToken(userID string, deviceID string) (string, error) {

	expirationTime := time.Now().Add(24 * time.Hour)

	claims := jwt.MapClaims{
		"sub":       userID,
		"exp":       expirationTime.Unix(),
		"device_id": deviceID,
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	secretKey := config.GetSecretKey()

	return token.SignedString([]byte(secretKey))
}

func (s *authAdminService) LogoutAdmin(userID, deviceID string) error {

	err := utils.DeleteSessionData(userID, deviceID)
	if err != nil {
		return fmt.Errorf("failed to delete session from Redis: %w", err)
	}

	return nil
}
 */