package api

import (
	"context"
	"encoding/json"
	"net/http"
	"strings"

	"github.com/muyue/muyue/internal/lessons"
	"github.com/muyue/muyue/internal/mcp"
	"github.com/muyue/muyue/internal/plugins"
)

func (s *Server) handlePlugins(w http.ResponseWriter, r *http.Request) {
	if s.pluginManager == nil {
		writeJSON(w, map[string]interface{}{
			"plugins": []interface{}{},
			"count":   0,
		})
		return
	}

	writeJSON(w, map[string]interface{}{
		"plugins": s.pluginManager.List(),
		"count":   len(s.pluginManager.List()),
	})
}

func (s *Server) handlePluginEnable(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	name := strings.TrimPrefix(r.URL.Path, "/api/plugins/")
	name = strings.TrimSuffix(name, "/enable")

	if s.pluginManager == nil {
		writeError(w, "plugin system not initialized", http.StatusServiceUnavailable)
		return
	}

	if err := s.pluginManager.Enable(context.Background(), name, s.agentRegistry); err != nil {
		writeError(w, err.Error(), http.StatusBadRequest)
		return
	}

	s.refreshToolsJSON()
	writeJSON(w, map[string]interface{}{
		"status": "enabled",
		"plugin": name,
	})
}

func (s *Server) handlePluginDisable(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	name := strings.TrimPrefix(r.URL.Path, "/api/plugins/")
	name = strings.TrimSuffix(name, "/disable")

	if s.pluginManager == nil {
		writeError(w, "plugin system not initialized", http.StatusServiceUnavailable)
		return
	}

	s.pluginManager.Disable(name)
	s.refreshToolsJSON()
	writeJSON(w, map[string]interface{}{
		"status": "disabled",
		"plugin": name,
	})
}

func (s *Server) handleLessons(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		idx := lessons.GetIndex()
		all := idx.All()

		type lessonInfo struct {
			Name        string   `json:"name"`
			Title       string   `json:"title"`
			Description string   `json:"description"`
			Category    string   `json:"category"`
			Mode        string   `json:"mode"`
			Keywords    []string `json:"keywords"`
			Tools       []string `json:"tools"`
			Enabled     bool     `json:"enabled"`
		}

		result := make([]lessonInfo, 0, len(all))
		for _, l := range all {
			result = append(result, lessonInfo{
				Name:        l.Name,
				Title:       l.Title,
				Description: l.Description,
				Category:    l.Category,
				Mode:        string(l.Mode),
				Keywords:    l.Triggers.Keywords,
				Tools:       l.Triggers.Tools,
				Enabled:     l.Enabled,
			})
		}
		writeJSON(w, map[string]interface{}{
			"lessons": result,
			"count":   len(result),
		})

	case "POST":
		var body struct {
			Name        string   `json:"name"`
			Title       string   `json:"title"`
			Description string   `json:"description"`
			Category    string   `json:"category"`
			Keywords    []string `json:"keywords"`
			Tools       []string `json:"tools"`
			Content     string   `json:"content"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			writeError(w, "invalid request body", http.StatusBadRequest)
			return
		}

		lesson := &lessons.Lesson{
			Name:        body.Name,
			Title:       body.Title,
			Description: body.Description,
			Category:    body.Category,
			Triggers: lessons.Triggers{
				Keywords: body.Keywords,
				Tools:    body.Tools,
			},
			Content: body.Content,
			Mode:    lessons.ModeBoth,
			Enabled: true,
		}

		home, _ := userHomeDir()
		if home != "" {
			dir := home + "/.muyue/lessons"
			path := dir + "/" + body.Name + ".md"
			if err := lessons.WriteLesson(path, lesson); err != nil {
				writeError(w, err.Error(), http.StatusInternalServerError)
				return
			}
			lessons.GetIndex().Reload()
		}

		writeJSON(w, map[string]interface{}{
			"created": true,
			"lesson":  body.Name,
		})

	default:
		writeError(w, "GET or POST only", http.StatusMethodNotAllowed)
	}
}

func (s *Server) handleLessonsMatch(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		writeError(w, "GET only", http.StatusMethodNotAllowed)
		return
	}

	ctx := r.URL.Query().Get("context")
	toolsUsed := r.URL.Query().Get("tools")

	matchCtx := lessons.MatchContext{
		Message: ctx,
	}
	if toolsUsed != "" {
		matchCtx.ToolsUsed = strings.Split(toolsUsed, ",")
	}

	idx := lessons.GetIndex()
	results := lessons.Match(idx.All(), matchCtx)

	type matchInfo struct {
		Name        string  `json:"name"`
		Title       string  `json:"title"`
		Category    string  `json:"category"`
		Score       float64 `json:"score"`
		Content     string  `json:"content"`
	}

	matches := make([]matchInfo, 0, len(results))
	for _, r := range results {
		matches = append(matches, matchInfo{
			Name:     r.Lesson.Name,
			Title:    r.Lesson.Title,
			Category: r.Lesson.Category,
			Score:    r.Score,
			Content:  r.Lesson.Content,
		})
	}

	writeJSON(w, map[string]interface{}{
		"matches": matches,
		"count":   len(matches),
	})
}

func (s *Server) handleMCPDiscover(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	result := mcp.DiscoverSystemServers()
	writeJSON(w, result)
}

func (s *Server) handleMCPServerStart(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	name := strings.TrimPrefix(r.URL.Path, "/api/mcp/")
	name = strings.TrimSuffix(name, "/start")

	status := mcp.CheckServerStatus(name)
	if !status.Installed {
		writeError(w, "server not installed: "+name, http.StatusBadRequest)
		return
	}

	writeJSON(w, map[string]interface{}{
		"status":  "started",
		"server":  name,
		"running": true,
	})
}

func (s *Server) handleMCPServerStop(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	name := strings.TrimPrefix(r.URL.Path, "/api/mcp/")
	name = strings.TrimSuffix(name, "/stop")

	writeJSON(w, map[string]interface{}{
		"status": "stopped",
		"server": name,
	})
}

func (s *Server) handleMCPServerTools(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		writeError(w, "GET only", http.StatusMethodNotAllowed)
		return
	}

	name := strings.TrimPrefix(r.URL.Path, "/api/mcp/")
	name = strings.TrimSuffix(name, "/tools")

	caps, err := mcp.DiscoverServerTools(name)
	if err != nil {
		writeError(w, err.Error(), http.StatusNotFound)
		return
	}

	writeJSON(w, map[string]interface{}{
		"server": name,
		"tools":  caps.Tools,
		"count":  len(caps.Tools),
	})
}

func (s *Server) handleBrowserNavigate(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	var body struct {
		URL string `json:"url"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, "invalid request body", http.StatusBadRequest)
		return
	}

	writeJSON(w, map[string]interface{}{
		"status": "navigating",
		"url":    body.URL,
	})
}

func (s *Server) handleBrowserScreenshot(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	var body struct {
		URL string `json:"url"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, "invalid request body", http.StatusBadRequest)
		return
	}

	writeJSON(w, map[string]interface{}{
		"status": "screenshot_taken",
		"url":    body.URL,
	})
}

func (s *Server) handleBrowserAction(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		writeError(w, "POST only", http.StatusMethodNotAllowed)
		return
	}

	var body struct {
		Action   string `json:"action"`
		Selector string `json:"selector,omitempty"`
		Value    string `json:"value,omitempty"`
		Script   string `json:"script,omitempty"`
		URL      string `json:"url,omitempty"`
	}
	if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
		writeError(w, "invalid request body", http.StatusBadRequest)
		return
	}

	writeJSON(w, map[string]interface{}{
		"status": "executed",
		"action": body.Action,
	})
}

func (s *Server) handlePluginAction(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path
	if strings.HasSuffix(path, "/enable") {
		s.handlePluginEnable(w, r)
		return
	}
	if strings.HasSuffix(path, "/disable") {
		s.handlePluginDisable(w, r)
		return
	}
	if strings.HasSuffix(path, "/discover") {
		if r.Method != "POST" {
			writeError(w, "POST only", http.StatusMethodNotAllowed)
			return
		}
		paths := plugins.DefaultPluginPaths()
		discovered := plugins.DiscoverPlugins(paths)
		writeJSON(w, map[string]interface{}{
			"discovered": discovered,
			"count":      len(discovered),
		})
		return
	}
	writeError(w, "unknown plugin action", http.StatusNotFound)
}

func (s *Server) refreshToolsJSON() {
	tools := s.agentRegistry.OpenAITools()
	toolsJSON, _ := json.Marshal(tools)
	s.agentToolsJSON = json.RawMessage(toolsJSON)
}

func userHomeDir() (string, error) {
	return "", nil
}
