package task

import (
	"fmt"
	"sort"
	"strings"

	"github.com/iomodo/staff/config"
	"github.com/iomodo/staff/tm"
)

// AutoAssigner handles intelligent task assignment to agents
type AutoAssigner struct {
	agents []config.AgentConfig
}

// NewAutoAssigner creates a new auto-assignment system
func NewAutoAssigner(agents []config.AgentConfig) *AutoAssigner {
	return &AutoAssigner{
		agents: agents,
	}
}

// AssignmentScore represents how well an agent matches a task
type AssignmentScore struct {
	AgentName string
	Score     float64
	Reasons   []string
}

// AssignTask automatically assigns a task to the best matching agent
func (a *AutoAssigner) AssignTask(task *tm.Task) (string, error) {
	if len(a.agents) == 0 {
		return "", fmt.Errorf("no agents available for assignment")
	}

	scores := a.calculateScores(task)
	if len(scores) == 0 {
		return "", fmt.Errorf("no suitable agent found for task")
	}

	// Sort by score (highest first)
	sort.Slice(scores, func(i, j int) bool {
		return scores[i].Score > scores[j].Score
	})

	bestMatch := scores[0]
	if bestMatch.Score == 0 {
		// No good match, assign to CEO as fallback
		return "ceo", nil
	}

	return bestMatch.AgentName, nil
}

// GetAssignmentRecommendations returns ranked recommendations for task assignment
func (a *AutoAssigner) GetAssignmentRecommendations(task *tm.Task) []AssignmentScore {
	scores := a.calculateScores(task)

	// Sort by score (highest first)
	sort.Slice(scores, func(i, j int) bool {
		return scores[i].Score > scores[j].Score
	})

	return scores
}

// calculateScores calculates assignment scores for all agents
func (a *AutoAssigner) calculateScores(task *tm.Task) []AssignmentScore {
	scores := make([]AssignmentScore, 0, len(a.agents))

	taskText := strings.ToLower(task.Title + " " + task.Description)
	taskKeywords := extractKeywords(taskText)

	for _, agent := range a.agents {
		score := &AssignmentScore{
			AgentName: agent.Name,
			Score:     0,
			Reasons:   make([]string, 0),
		}

		// Score based on task type keywords
		score.Score += a.scoreTaskTypes(agent.TaskTypes, taskKeywords, score)

		// Score based on capabilities
		score.Score += a.scoreCapabilities(agent.Capabilities, taskKeywords, score)

		// Score based on task priority and agent model
		score.Score += a.scorePriorityModelMatch(task.Priority, agent.Model, score)

		// Score based on explicit agent mention in task
		score.Score += a.scoreExplicitMention(agent.Name, agent.Role, taskText, score)

		scores = append(scores, *score)
	}

	return scores
}

// scoreTaskTypes scores based on task type matching
func (a *AutoAssigner) scoreTaskTypes(agentTypes []string, taskKeywords []string, score *AssignmentScore) float64 {
	typeScore := 0.0

	for _, agentType := range agentTypes {
		for _, keyword := range taskKeywords {
			if strings.Contains(keyword, agentType) || strings.Contains(agentType, keyword) {
				typeScore += 3.0
				score.Reasons = append(score.Reasons, fmt.Sprintf("matches task type: %s", agentType))
			}
		}
	}

	return typeScore
}

// scoreCapabilities scores based on capability matching
func (a *AutoAssigner) scoreCapabilities(capabilities []string, taskKeywords []string, score *AssignmentScore) float64 {
	capScore := 0.0

	for _, capability := range capabilities {
		for _, keyword := range taskKeywords {
			if strings.Contains(keyword, capability) || strings.Contains(capability, keyword) {
				capScore += 2.0
				score.Reasons = append(score.Reasons, fmt.Sprintf("has capability: %s", capability))
			}
		}
	}

	return capScore
}

// scorePriorityModelMatch scores based on priority and model sophistication
func (a *AutoAssigner) scorePriorityModelMatch(priority tm.TaskPriority, model string, score *AssignmentScore) float64 {
	priorityScore := 0.0

	// High priority tasks prefer more capable models
	if priority == tm.PriorityHigh && strings.Contains(model, "gpt-4") {
		priorityScore += 1.0
		score.Reasons = append(score.Reasons, "high priority task matches advanced model")
	}

	// Medium/low priority can use efficient models
	if priority != tm.PriorityHigh && strings.Contains(model, "gpt-3.5") {
		priorityScore += 0.5
		score.Reasons = append(score.Reasons, "priority matches model efficiency")
	}

	return priorityScore
}

// scoreExplicitMention scores based on explicit agent/role mentions
func (a *AutoAssigner) scoreExplicitMention(agentName, agentRole, taskText string, score *AssignmentScore) float64 {
	mentionScore := 0.0

	// Check for explicit agent name mention
	if strings.Contains(taskText, agentName) {
		mentionScore += 5.0
		score.Reasons = append(score.Reasons, "explicitly mentioned by name")
	}

	// Check for role mention
	roleLower := strings.ToLower(agentRole)
	if strings.Contains(taskText, roleLower) {
		mentionScore += 4.0
		score.Reasons = append(score.Reasons, "role mentioned in task")
	}

	return mentionScore
}

// extractKeywords extracts relevant keywords from task text
func extractKeywords(text string) []string {
	// Simple keyword extraction - split by common delimiters
	words := strings.FieldsFunc(text, func(c rune) bool {
		return c == ' ' || c == ',' || c == '.' || c == ':' || c == ';' || c == '\n' || c == '\t'
	})

	// Filter out common stop words and short words
	stopWords := map[string]bool{
		"the": true, "a": true, "an": true, "and": true, "or": true, "but": true,
		"in": true, "on": true, "at": true, "to": true, "for": true, "of": true,
		"with": true, "by": true, "is": true, "are": true, "was": true, "were": true,
		"be": true, "been": true, "have": true, "has": true, "had": true, "do": true,
		"does": true, "did": true, "will": true, "would": true, "could": true, "should": true,
	}

	keywords := make([]string, 0)
	for _, word := range words {
		word = strings.ToLower(strings.TrimSpace(word))
		if len(word) > 2 && !stopWords[word] {
			keywords = append(keywords, word)
		}
	}

	return keywords
}

// ValidateAssignment checks if an assignment is valid
func (a *AutoAssigner) ValidateAssignment(agentName string, task *tm.Task) error {
	// Check if agent exists
	for _, agent := range a.agents {
		if agent.Name == agentName {
			return nil
		}
	}

	return fmt.Errorf("agent '%s' not found", agentName)
}

// GetAgentCapabilities returns the capabilities of a specific agent
func (a *AutoAssigner) GetAgentCapabilities(agentName string) ([]string, error) {
	for _, agent := range a.agents {
		if agent.Name == agentName {
			return agent.Capabilities, nil
		}
	}

	return nil, fmt.Errorf("agent '%s' not found", agentName)
}

// GetRecommendationExplanation returns a human-readable explanation for assignment
func (a *AutoAssigner) GetRecommendationExplanation(task *tm.Task, agentName string) string {
	recommendations := a.GetAssignmentRecommendations(task)

	for _, rec := range recommendations {
		if rec.AgentName == agentName {
			if len(rec.Reasons) == 0 {
				return fmt.Sprintf("Agent %s assigned (score: %.1f)", agentName, rec.Score)
			}

			reasons := strings.Join(rec.Reasons, ", ")
			return fmt.Sprintf("Agent %s assigned (score: %.1f) because: %s", agentName, rec.Score, reasons)
		}
	}

	return fmt.Sprintf("Agent %s assigned (manual override)", agentName)
}
