// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

// Package goal provides MCP tools for goal operations.
package goal

import (
	"context"
	"fmt"
	"strings"

	"git.secluded.site/go-lunatask"
	"git.secluded.site/lune/internal/mcp/shared"
	"github.com/modelcontextprotocol/go-sdk/mcp"
)

// ListToolName is the name of the list goals tool.
const ListToolName = "list_goals"

// ListToolDescription describes the list goals tool for LLMs.
const ListToolDescription = `Lists goals for an area. Use list_areas to find area IDs first.

Required:
- area_id: Area UUID, deep link, or config key

Returns goal metadata (id, name, key) for the specified area.`

// ListInput is the input schema for listing goals.
type ListInput struct {
	AreaID string `json:"area_id" jsonschema:"required"`
}

// Summary represents a goal in the list output.
type Summary struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	Key  string `json:"key"`
}

// ListOutput is the output schema for listing goals.
type ListOutput struct {
	Goals  []Summary `json:"goals"`
	Count  int       `json:"count"`
	AreaID string    `json:"area_id"`
}

// Handler handles goal tool requests.
type Handler struct {
	areas []shared.AreaProvider
}

// NewHandler creates a new goal tool handler.
func NewHandler(areas []shared.AreaProvider) *Handler {
	return &Handler{areas: areas}
}

// HandleList lists goals for an area.
func (h *Handler) HandleList(
	_ context.Context,
	_ *mcp.CallToolRequest,
	input ListInput,
) (*mcp.CallToolResult, ListOutput, error) {
	area := h.resolveAreaRef(input.AreaID)
	if area == nil {
		return shared.ErrorResult("unknown area: " + input.AreaID), ListOutput{}, nil
	}

	summaries := make([]Summary, 0, len(area.Goals))

	for _, goal := range area.Goals {
		summaries = append(summaries, Summary{
			ID:   goal.ID,
			Name: goal.Name,
			Key:  goal.Key,
		})
	}

	output := ListOutput{
		Goals:  summaries,
		Count:  len(summaries),
		AreaID: area.ID,
	}

	text := formatListText(summaries, area.Name)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{Text: text}},
	}, output, nil
}

// resolveAreaRef resolves an area reference to an AreaProvider.
// Accepts config key, UUID, or deep link.
func (h *Handler) resolveAreaRef(input string) *shared.AreaProvider {
	// Try UUID or deep link first
	if _, id, err := lunatask.ParseReference(input); err == nil {
		for i := range h.areas {
			if h.areas[i].ID == id {
				return &h.areas[i]
			}
		}
	}

	// Try config key lookup
	for i := range h.areas {
		if h.areas[i].Key == input {
			return &h.areas[i]
		}
	}

	return nil
}

func formatListText(goals []Summary, areaName string) string {
	if len(goals) == 0 {
		return fmt.Sprintf("No goals configured for area %q", areaName)
	}

	var text strings.Builder

	text.WriteString(fmt.Sprintf("Found %d goal(s) in %q:\n", len(goals), areaName))

	for _, g := range goals {
		text.WriteString(fmt.Sprintf("- %s: %s (%s)\n", g.Key, g.Name, g.ID))
	}

	return text.String()
}
