package dbstore

import (
	"context"
	"fmt"

	"git.linuxforward.com/byop/byop-engine/models"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// CreateUser creates a new user using GORM
func (s *SQLiteStore) CreateUser(ctx context.Context, user *models.User) error {
	result := s.db.WithContext(ctx).Create(user)
	if result.Error != nil {
		return fmt.Errorf("failed to create user: %w", result.Error)
	}
	return nil
}

// GetUserByEmail retrieves a user by email using GORM
func (s *SQLiteStore) GetUserByEmail(ctx context.Context, email string) (*models.User, error) {
	var user models.User
	result := s.db.WithContext(ctx).Where("email = ?", email).First(&user)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, models.NewErrNotFound(fmt.Sprintf("user with email %s not found", email), result.Error)
		}
		return nil, fmt.Errorf("failed to get user by email: %w", result.Error)
	}
	return &user, nil
}

// GetUsers retrieves all users using GORM
func (s *SQLiteStore) GetUsers(ctx context.Context) ([]*models.User, error) {
	var users []*models.User
	result := s.db.WithContext(ctx).Find(&users)
	if result.Error != nil {
		return nil, fmt.Errorf("failed to get users: %w", result.Error)
	}
	return users, nil
}

// GetUserByID retrieves a user by ID using GORM
func (s *SQLiteStore) GetUserByID(ctx context.Context, id uint) (*models.User, error) {
	var user models.User
	result := s.db.WithContext(ctx).First(&user, id)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			return nil, models.NewErrNotFound(fmt.Sprintf("user with ID %d not found", id), result.Error)
		}
		return nil, fmt.Errorf("failed to get user by ID: %w", result.Error)
	}
	return &user, nil
}

// GetByUsername retrieves a user by username (assuming username is email)
func (s *SQLiteStore) GetByUsername(ctx context.Context, username string) (*models.User, error) {
	return s.GetUserByEmail(ctx, username)
}

// UpdateUser updates an existing user using GORM
func (s *SQLiteStore) UpdateUser(ctx context.Context, user *models.User) error {
	result := s.db.WithContext(ctx).Save(user)
	if result.Error != nil {
		return fmt.Errorf("failed to update user: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("user with ID %d not found for update", user.ID), nil)
	}
	return nil
}

// CreateDefaultAdmin creates a default admin user if none exists
func (s *SQLiteStore) CreateDefaultAdmin(ctx context.Context) error {
	_, err := s.GetUserByEmail(ctx, "admin@byop.local")
	if err == nil {
		// Admin user already exists
		return nil
	}

	if !models.IsErrNotFound(err) {
		return err
	}

	hashedPassword, hashErr := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost)
	if hashErr != nil {
		return hashErr
	}

	admin := &models.User{
		Email:    "admin@byop.local",
		Password: string(hashedPassword),
		Name:     "Administrator",
		Role:     "admin",
		Active:   true,
	}

	return s.CreateUser(ctx, admin)
}

// DeleteUser deletes a user by ID using GORM
func (s *SQLiteStore) DeleteUser(ctx context.Context, id uint) error {
	result := s.db.WithContext(ctx).Delete(&models.User{}, id)
	if result.Error != nil {
		return fmt.Errorf("failed to delete user: %w", result.Error)
	}
	if result.RowsAffected == 0 {
		return models.NewErrNotFound(fmt.Sprintf("user with ID %d not found for deletion", id), nil)
	}
	return nil
}
