package workflow

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/muyue/muyue/internal/config"
	"github.com/muyue/muyue/internal/orchestrator"
)

type Planner struct {
	orchestrator *orchestrator.Orchestrator
}

func NewPlanner(cfg *config.MuyueConfig) (*Planner, error) {
	orb, err := orchestrator.New(cfg)
	if err != nil {
		return nil, err
	}
	orb.SetSystemPrompt(plannerSystemPrompt)
	return &Planner{orchestrator: orb}, nil
}

func (p *Planner) GeneratePlan(ctx context.Context, goal string) ([]Step, error) {
	prompt := buildPlanPrompt(goal)

	messages := []orchestrator.Message{
		{Role: "user", Content: orchestrator.TextContent(prompt)},
	}

	resp, err := p.orchestrator.SendWithTools(messages)
	if err != nil {
		return nil, err
	}

	if len(resp.Choices) == 0 || resp.Choices[0].Message.Content == "" {
		return nil, fmt.Errorf("no plan generated")
	}

	content := resp.Choices[0].Message.Content
	plan, err := parsePlanResponse(content)
	if err != nil {
		return nil, err
	}

	return plan, nil
}

func buildPlanPrompt(goal string) string {
	return fmt.Sprintf(`Tu es un planificateur de workflows pour Muyue. L'utilisateur veut accomplir la tâche suivante:

"%s"

Analyse cette tâche et génère un plan d'exécution en une série d'étapes. Chaque étape est un appel d'outil.

Les outils disponibles sont:
- terminal: Exécuter une commande shell
- read_file: Lire un fichier
- list_files: Lister les fichiers d'un répertoire
- search_files: Rechercher des fichiers par pattern
- grep_content: Rechercher du texte dans des fichiers
- get_config: Lire la configuration Muyue
- set_provider: Configurer un provider AI
- manage_ssh: Gérer les connexions SSH
- web_fetch: Récupérer le contenu d'une URL

Réponds UNIQUEMENT avec un JSON valide représentant un tableau d'étapes, sans texte avant ou après:

[
  {"name": "Nom de l'étape", "tool": "terminal", "args": {"command": "ls -la"}},
  {"name": "Lire le fichier config", "tool": "read_file", "args": {"path": "~/.muyue/config.json"}}
]

Règles:
- Chaque étape doit avoir: name, tool, args
- Les args varient selon le tool (voir les définitions)
- Sois précis dans les commandes
- Sépare en étapes logiques
- Ne génère pas plus de 10 étapes`, goal)
}

func parsePlanResponse(content string) ([]Step, error) {
	content = strings.TrimSpace(content)

	var jsonStr string
	if strings.HasPrefix(content, "```json") {
		lines := strings.Split(content, "\n")
		var jsonLines []string
		for _, line := range lines[1:] {
			if strings.HasPrefix(line, "```") {
				break
			}
			jsonLines = append(jsonLines, line)
		}
		jsonStr = strings.Join(jsonLines, "\n")
	} else if strings.HasPrefix(content, "```") {
		lines := strings.Split(content, "\n")
		var jsonLines []string
		for _, line := range lines[1:] {
			if strings.HasPrefix(line, "```") {
				break
			}
			jsonLines = append(jsonLines, line)
		}
		jsonStr = strings.Join(jsonLines, "\n")
	} else {
		jsonStr = content
	}

	var rawSteps []map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr), &rawSteps); err != nil {
		return nil, fmt.Errorf("failed to parse plan JSON: %v\nContent: %s", err, content)
	}

	steps := make([]Step, 0, len(rawSteps))
	for i, raw := range rawSteps {
		step := Step{
			ID:     fmt.Sprintf("step-%d", i),
			Status: StatusPending,
		}

		if name, ok := raw["name"].(string); ok {
			step.Name = name
		} else {
			step.Name = fmt.Sprintf("Step %d", i+1)
		}

		if tool, ok := raw["tool"].(string); ok {
			step.Tool = tool
			step.Type = TypeToolCall
		}

		if args, ok := raw["args"].(map[string]interface{}); ok {
			argsJSON, err := json.Marshal(args)
			if err == nil {
				step.Args = argsJSON
			}
		}

		if tool, ok := raw["type"].(string); ok {
			switch tool {
			case "approval":
				step.Type = TypeApproval
			case "condition":
				step.Type = TypeCondition
				if cond, ok := raw["condition"].(string); ok {
					step.Condition = cond
				}
			default:
				step.Type = TypeToolCall
			}
		}

		steps = append(steps, step)
	}

	return steps, nil
}

const plannerSystemPrompt = `Tu es un planificateur de workflows pour Muyue. Tu génères des plans d'exécution sous forme de tableaux JSON.

RÈGLES :
1. Analyse l'objectif → identifie les outils → décompose en étapes
2. Chaque étape : {"name": string, "tool": string, "args": object}
3. Max 10 étapes par plan
4. Ordonne par dépendances (les lectures avant les écritures)
5. Préfère les commandes non-interactives
6. Utilise crush_run pour les tâches complexes multi-fichiers

Outils : terminal, crush_run, read_file, list_files, search_files, grep_content, get_config, set_provider, manage_ssh, web_fetch

Réponds UNIQUEMENT en JSON valide, sans texte avant/après.`

const _ = plannerSystemPrompt