package bootstrap

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/google/uuid"

	"github.com/ocdp/cluster-service/internal/adapter/output"
	"github.com/ocdp/cluster-service/internal/domain/entity"
	"github.com/ocdp/cluster-service/internal/pkg/password"
)

// Seeder 预注入管理器
type Seeder struct {
	repos          *output.Repositories
	passwordHasher *password.Hasher
	config         *BootstrapConfig
}

// NewSeeder 创建预注入管理器
func NewSeeder(repos *output.Repositories, passwordHasher *password.Hasher, config *BootstrapConfig) *Seeder {
	return &Seeder{
		repos:          repos,
		passwordHasher: passwordHasher,
		config:         config,
	}
}

// SeedAll 执行所有预注入
func (s *Seeder) SeedAll(ctx context.Context) error {
	if !s.config.Enabled {
		log.Println("  ℹ️  Bootstrap seeding is disabled")
		return nil
	}

	log.Println("  🌱 Starting bootstrap seeding...")

	// 1. 注入用户
	if err := s.seedUsers(ctx); err != nil {
		return fmt.Errorf("failed to seed users: %w", err)
	}

	// 2. 注入 Registries
	if err := s.seedRegistries(ctx); err != nil {
		return fmt.Errorf("failed to seed registries: %w", err)
	}

	// 3. 注入 Clusters
	if err := s.seedClusters(ctx); err != nil {
		return fmt.Errorf("failed to seed clusters: %w", err)
	}

	log.Println("  ✅ Bootstrap seeding completed")
	return nil
}

// seedUsers 注入用户
func (s *Seeder) seedUsers(ctx context.Context) error {
	if len(s.config.Users) == 0 {
		log.Println("     ↳ No users to seed")
		return nil
	}

	log.Printf("     ↳ Seeding %d user(s)...", len(s.config.Users))

	for _, userSeed := range s.config.Users {
		// 检查用户是否已存在
		existingUser, _ := s.repos.UserRepo.GetByUsername(ctx, userSeed.Username)
		if existingUser != nil {
			log.Printf("       ⊙ User '%s' already exists, skipping", userSeed.Username)
			continue
		}

		// 哈希密码
		passwordHash, err := s.passwordHasher.Hash(userSeed.Password)
		if err != nil {
			log.Printf("       ✗ Failed to hash password for user '%s': %v", userSeed.Username, err)
			continue
		}

		// 创建用户
		user := entity.NewUser(userSeed.Username, passwordHash, userSeed.Email)
		user.ID = uuid.New().String()
		if userSeed.Role != "" {
			user.Role = userSeed.Role
		}
		if user.Role == "admin" {
			user.WorkspaceID = entity.DefaultWorkspaceID
		}

		if err := s.repos.UserRepo.Create(ctx, user); err != nil {
			log.Printf("       ✗ Failed to create user '%s': %v", userSeed.Username, err)
			continue
		}

		log.Printf("       ✓ User '%s' created", userSeed.Username)
	}

	return nil
}

// seedRegistries 注入 Registries
func (s *Seeder) seedRegistries(ctx context.Context) error {
	if len(s.config.Registries) == 0 {
		log.Println("     ↳ No registries to seed")
		return nil
	}

	log.Printf("     ↳ Seeding %d registry(ies)...", len(s.config.Registries))

	ownerID := s.bootstrapOwnerID(ctx)
	for _, registrySeed := range s.config.Registries {
		// 检查 Registry 是否已存在
		existingRegistry, _ := s.repos.RegistryRepo.GetByName(ctx, registrySeed.Name)
		if existingRegistry != nil {
			log.Printf("       ⊙ Registry '%s' already exists, skipping", registrySeed.Name)
			continue
		}

		// 创建 Registry
		registry := &entity.Registry{
			ID:          uuid.New().String(),
			Name:        registrySeed.Name,
			WorkspaceID: entity.DefaultWorkspaceID,
			OwnerID:     ownerID,
			Visibility:  "global_shared",
			URL:         registrySeed.URL,
			Description: registrySeed.Description,
			Username:    registrySeed.Username,
			Password:    registrySeed.Password,
			Insecure:    registrySeed.Insecure,
			CreatedAt:   time.Now(),
			UpdatedAt:   time.Now(),
		}

		if err := s.repos.RegistryRepo.Create(ctx, registry); err != nil {
			log.Printf("       ✗ Failed to create registry '%s': %v", registrySeed.Name, err)
			continue
		}

		log.Printf("       ✓ Registry '%s' created (credentials encrypted)", registrySeed.Name)
	}

	return nil
}

// seedClusters 注入 Clusters
func (s *Seeder) seedClusters(ctx context.Context) error {
	if len(s.config.Clusters) == 0 {
		log.Println("     ↳ No clusters to seed")
		return nil
	}

	log.Printf("     ↳ Seeding %d cluster(s)...", len(s.config.Clusters))

	ownerID := s.bootstrapOwnerID(ctx)
	for _, clusterSeed := range s.config.Clusters {
		// 检查 Cluster 是否已存在
		existingCluster, _ := s.repos.ClusterRepo.GetByName(ctx, clusterSeed.Name)
		if existingCluster != nil {
			log.Printf("       ⊙ Cluster '%s' already exists, skipping", clusterSeed.Name)
			continue
		}

		// 创建 Cluster
		cluster := &entity.Cluster{
			ID:          uuid.New().String(),
			Name:        clusterSeed.Name,
			WorkspaceID: entity.DefaultWorkspaceID,
			OwnerID:     ownerID,
			Visibility:  "global_shared",
			Host:        clusterSeed.Host,
			Description: clusterSeed.Description,
			CAData:      clusterSeed.CAData,
			CertData:    clusterSeed.CertData,
			KeyData:     clusterSeed.KeyData,
			Token:       clusterSeed.Token,
			CreatedAt:   time.Now(),
			UpdatedAt:   time.Now(),
		}

		if err := s.repos.ClusterRepo.Create(ctx, cluster); err != nil {
			log.Printf("       ✗ Failed to create cluster '%s': %v", clusterSeed.Name, err)
			continue
		}

		log.Printf("       ✓ Cluster '%s' created (credentials encrypted)", clusterSeed.Name)
	}

	return nil
}

func (s *Seeder) bootstrapOwnerID(ctx context.Context) string {
	for _, userSeed := range s.config.Users {
		if userSeed.Role == "admin" {
			if user, err := s.repos.UserRepo.GetByUsername(ctx, userSeed.Username); err == nil && user != nil {
				return user.ID
			}
		}
	}
	users, err := s.repos.UserRepo.List(ctx)
	if err != nil {
		return ""
	}
	for _, user := range users {
		if user.Role == "admin" {
			return user.ID
		}
	}
	return ""
}
