package agent

import (
	"context"
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/anthropic/isdp/internal/model"
	"github.com/anthropic/isdp/internal/repo"
	"github.com/google/uuid"
)

// ConfigGenerator 配置生成器接口（避免循环导入）
// 实现者需要在调用方包中创建adapter
type ConfigGenerator interface {
	GenerateAgentConfig(ctx context.Context, agentId uuid.UUID, cliType string) (skillsCount, commandsCount, subagentsCount, rulesCount, settingsCount int, err error)
}

// ConfigService Agent配置服务
type ConfigService struct {
	repo          *repo.AgentConfigRepository
	baseAgentRepo *repo.BaseAgentRepository
	cache         map[uuid.UUID]*model.AgentRoleConfig
	cacheMu       sync.RWMutex
}

// NewConfigService 创建配置服务
func NewConfigService(repo *repo.AgentConfigRepository, baseAgentRepo *repo.BaseAgentRepository) *ConfigService {
	return &ConfigService{
		repo:          repo,
		baseAgentRepo: baseAgentRepo,
		cache:         make(map[uuid.UUID]*model.AgentRoleConfig),
	}
}

// GetByID 根据ID获取配置
func (s *ConfigService) GetByID(ctx context.Context, id uuid.UUID) (*model.AgentRoleConfig, error) {
	s.cacheMu.RLock()
	if config, ok := s.cache[id]; ok {
		s.cacheMu.RUnlock()
		return config, nil
	}
	s.cacheMu.RUnlock()

	config, err := s.repo.FindByID(ctx, id)
	if err != nil {
		return nil, err
	}

	// 填充 BaseAgent 详情
	s.fillBaseAgent(ctx, config)

	s.cacheMu.Lock()
	s.cache[id] = config
	s.cacheMu.Unlock()

	return config, nil
}

// GetByRole 根据角色获取配置
func (s *ConfigService) GetByRole(ctx context.Context, role model.AgentRole) ([]*model.AgentRoleConfig, error) {
	configs, err := s.repo.FindByRole(ctx, role)
	if err != nil {
		return nil, err
	}

	// 填充 BaseAgent 详情
	s.fillBaseAgentForList(ctx, configs)

	return configs, nil
}

// GetDefaultByRole 获取角色的默认配置
func (s *ConfigService) GetDefaultByRole(ctx context.Context, role model.AgentRole) (*model.AgentRoleConfig, error) {
	configs, err := s.repo.FindByRole(ctx, role)
	if err != nil {
		return nil, err
	}
	for _, c := range configs {
		if c.IsDefault {
			return c, nil
		}
	}
	if len(configs) > 0 {
		return configs[0], nil
	}
	return nil, ErrConfigNotFound
}

// Create 创建配置
func (s *ConfigService) Create(ctx context.Context, req *model.CreateAgentRequest) (*model.AgentRoleConfig, error) {
	// 角色必须由调用方指定，默认为 agent
	role := req.Role
	if role == "" {
		role = model.AgentRoleAgent
	}

	config := &model.AgentRoleConfig{
		ID:             uuid.New(),
		Name:           req.Name,
		Role:           role,
		BaseAgentID:    req.BaseAgentID,
		Description:    req.Description,
		SystemPrompt:   req.SystemPrompt,
		MaxTokens:      req.MaxTokens,
		Temperature:    req.Temperature,
		IsDefault:      req.IsDefault,
		MentionPatterns: req.MentionPatterns,
			RequiresHuman:  req.RequiresHuman,
		CreatedAt:      time.Now(),
		UpdatedAt:      time.Now(),
	}

	if err := s.repo.Create(ctx, config); err != nil {
		return nil, err
	}

	s.cacheMu.Lock()
	s.cache[config.ID] = config
	s.cacheMu.Unlock()

	return config, nil
}

// Update 更新配置
func (s *ConfigService) Update(ctx context.Context, id uuid.UUID, req *model.CreateAgentRequest) (*model.AgentRoleConfig, error) {
	config, err := s.repo.FindByID(ctx, id)
	if err != nil {
		return nil, err
	}

	// 角色必须由调用方指定，默认为 agent
	role := req.Role
	if role == "" {
		role = model.AgentRoleAgent
	}

	config.Name = req.Name
	config.Role = role
	config.BaseAgentID = req.BaseAgentID
	config.Description = req.Description
	config.SystemPrompt = req.SystemPrompt
	config.MaxTokens = req.MaxTokens
	config.Temperature = req.Temperature
	config.IsDefault = req.IsDefault
	config.RequiresHuman = req.RequiresHuman
	// 直接更新 mentionPatterns
	config.MentionPatterns = req.MentionPatterns
	config.UpdatedAt = time.Now()

	if err := s.repo.Update(ctx, config); err != nil {
		return nil, err
	}

	s.cacheMu.Lock()
	s.cache[id] = config
	s.cacheMu.Unlock()

	return config, nil
}

// Delete 删除配置
func (s *ConfigService) Delete(ctx context.Context, id uuid.UUID) error {
	if err := s.repo.Delete(ctx, id); err != nil {
		return err
	}

	s.cacheMu.Lock()
	delete(s.cache, id)
	s.cacheMu.Unlock()

	return nil
}

// List 列出所有配置
func (s *ConfigService) List(ctx context.Context) ([]*model.AgentRoleConfig, error) {
	configs, err := s.repo.List(ctx)
	if err != nil {
		return nil, err
	}

	// 填充 BaseAgent 详情
	s.fillBaseAgentForList(ctx, configs)

	return configs, nil
}

// InvalidateCache 失效指定Agent的缓存（配置生成后需要调用）
func (s *ConfigService) InvalidateCache(id uuid.UUID) {
	s.cacheMu.Lock()
	delete(s.cache, id)
	s.cacheMu.Unlock()
}

// RefreshCache 刷新指定Agent的缓存（从数据库重新加载）
func (s *ConfigService) RefreshCache(ctx context.Context, id uuid.UUID) error {
	s.cacheMu.Lock()
	delete(s.cache, id)
	s.cacheMu.Unlock()

	// 从数据库重新加载并缓存
	config, err := s.repo.FindByID(ctx, id)
	if err != nil {
		return err
	}

	s.cacheMu.Lock()
	s.cache[id] = config
	s.cacheMu.Unlock()

	return nil
}

var (
	ErrConfigNotFound = errors.New("agent config not found")
)

// BatchGenerateConfig 批量生成配置
func (s *ConfigService) BatchGenerateConfig(ctx context.Context,
	agentIds []uuid.UUID, cliType string, generator ConfigGenerator) (*model.BatchGenerateResult, error) {

	result := &model.BatchGenerateResult{
		Total:   len(agentIds),
		Results: make([]model.GenerateResultItem, len(agentIds)),
	}

	if cliType == "" {
		cliType = "claude_code"
	}

	// 使用worker pool限制并发数
	const maxWorkers = 5
	sem := make(chan struct{}, maxWorkers)
	var wg sync.WaitGroup
	var mu sync.Mutex

	for i, id := range agentIds {
		wg.Add(1)
		sem <- struct{}{} // 获取信号量

		go func(idx int, agentId uuid.UUID) {
			defer wg.Done()
			defer func() { <-sem }() // 释放信号量

			item := &model.GenerateResultItem{AgentId: agentId}

			config, err := s.GetByID(ctx, agentId)
			if err != nil {
				item.Status = "failed"
				item.Error = "Agent不存在"
			} else {
				item.AgentName = config.Name
				// 调用配置生成器生成配置
				skillsCount, commandsCount, subagentsCount, rulesCount, settingsCount, err := generator.GenerateAgentConfig(ctx, agentId, cliType)
				if err != nil {
					item.Status = "failed"
					item.Error = err.Error()
				} else {
					item.Status = "success"
					item.SkillsCount = skillsCount
					item.CommandsCount = commandsCount
					item.SubagentsCount = subagentsCount
					item.RulesCount = rulesCount
					item.SettingsCount = settingsCount
				}
			}

			mu.Lock()
			result.Results[idx] = *item
			if item.Status == "success" {
				result.Success++
			} else {
				result.Failed++
			}
			mu.Unlock()
		}(i, id)
	}

	wg.Wait()
	return result, nil
}

// BatchUpdateBaseAgent 批量修改基础Agent
func (s *ConfigService) BatchUpdateBaseAgent(ctx context.Context,
	agentIds []uuid.UUID, baseAgentId uuid.UUID) (*model.BatchUpdateResult, error) {

	// 验证目标BaseAgent存在
	baseAgent, err := s.baseAgentRepo.FindByID(ctx, baseAgentId)
	if err != nil {
		return nil, fmt.Errorf("目标基础Agent不存在")
	}

	result := &model.BatchUpdateResult{
		Total:   len(agentIds),
		Results: make([]model.UpdateResultItem, len(agentIds)),
	}

	for i, id := range agentIds {
		item := &model.UpdateResultItem{AgentId: id}

		config, err := s.GetByID(ctx, id)
		if err != nil {
			item.Status = "failed"
			item.Error = "Agent不存在"
		} else {
			item.AgentName = config.Name
			config.BaseAgentID = baseAgentId
			config.UpdatedAt = time.Now()

			if err := s.repo.Update(ctx, config); err != nil {
				item.Status = "failed"
				item.Error = err.Error()
			} else {
				item.Status = "success"
				item.BaseAgentName = baseAgent.Name

				// 更新缓存
				s.cacheMu.Lock()
				s.cache[id] = config
				s.cacheMu.Unlock()
			}
		}

		result.Results[i] = *item
		if item.Status == "success" {
			result.Success++
		} else {
			result.Failed++
		}
	}

	return result, nil
}

// fillBaseAgent 填充 AgentRoleConfig 的 BaseAgent 详情
func (s *ConfigService) fillBaseAgent(ctx context.Context, config *model.AgentRoleConfig) error {
	if config == nil {
		return nil
	}

	// 如果有指定的 BaseAgentID，查询对应的 BaseAgent
	if config.BaseAgentID != uuid.Nil {
		baseAgent, err := s.baseAgentRepo.FindByID(ctx, config.BaseAgentID)
		if err == nil {
			config.BaseAgent = baseAgent
			return nil
		}
	}

	// 如果没有指定或查询失败，获取默认 BaseAgent
	defaultAgent, err := s.baseAgentRepo.FindDefault(ctx)
	if err == nil && defaultAgent != nil {
		config.BaseAgent = defaultAgent
	}

	return nil
}

// fillBaseAgentForList 批量填充多个 AgentRoleConfig 的 BaseAgent 详情
func (s *ConfigService) fillBaseAgentForList(ctx context.Context, configs []*model.AgentRoleConfig) error {
	for _, config := range configs {
		s.fillBaseAgent(ctx, config)
	}
	return nil
}