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

package task

import (
	"context"
	"fmt"
	"strings"
	"time"

	"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 tasks tool.
const ListToolName = "list_tasks"

// ListToolDescription describes the list tasks tool for LLMs.
const ListToolDescription = `Lists tasks from Lunatask.

Optional filters:
- area_id: Filter by area UUID
- status: Filter by status (later, next, started, waiting, completed)
- include_completed: Include completed tasks (default: false, only shows today's)

Note: Due to end-to-end encryption, task names and notes are not available.
Only metadata (ID, status, dates, priority, etc.) is returned.

Returns a list of tasks with their metadata and deep links.`

// ListInput is the input schema for listing tasks.
type ListInput struct {
	AreaID           *string `json:"area_id,omitempty"`
	Status           *string `json:"status,omitempty"`
	IncludeCompleted *bool   `json:"include_completed,omitempty"`
}

// ListOutput is the output schema for listing tasks.
type ListOutput struct {
	Tasks []Summary `json:"tasks"`
	Count int       `json:"count"`
}

// Summary represents a task in list output.
type Summary struct {
	DeepLink    string  `json:"deep_link"`
	Status      *string `json:"status,omitempty"`
	Priority    *int    `json:"priority,omitempty"`
	ScheduledOn *string `json:"scheduled_on,omitempty"`
	CreatedAt   string  `json:"created_at"`
	AreaID      *string `json:"area_id,omitempty"`
	GoalID      *string `json:"goal_id,omitempty"`
}

// HandleList lists tasks.
func (h *Handler) HandleList(
	ctx context.Context,
	_ *mcp.CallToolRequest,
	input ListInput,
) (*mcp.CallToolResult, ListOutput, error) {
	if input.AreaID != nil {
		if err := lunatask.ValidateUUID(*input.AreaID); err != nil {
			return shared.ErrorResult("invalid area_id: expected UUID"), ListOutput{}, nil
		}
	}

	if input.Status != nil {
		if _, err := lunatask.ParseTaskStatus(*input.Status); err != nil {
			return shared.ErrorResult("invalid status: must be later, next, started, waiting, or completed"), ListOutput{}, nil
		}
	}

	tasks, err := h.client.ListTasks(ctx, nil)
	if err != nil {
		return shared.ErrorResult(err.Error()), ListOutput{}, nil
	}

	opts := &lunatask.TaskFilterOptions{
		AreaID:           input.AreaID,
		IncludeCompleted: input.IncludeCompleted != nil && *input.IncludeCompleted,
		Today:            time.Now(),
	}

	if input.Status != nil {
		s := lunatask.TaskStatus(*input.Status)
		opts.Status = &s
	}

	filtered := lunatask.FilterTasks(tasks, opts)
	summaries := buildSummaries(filtered)
	text := formatListText(summaries)

	return &mcp.CallToolResult{
			Content: []mcp.Content{&mcp.TextContent{Text: text}},
		}, ListOutput{
			Tasks: summaries,
			Count: len(summaries),
		}, nil
}

func buildSummaries(tasks []lunatask.Task) []Summary {
	summaries := make([]Summary, 0, len(tasks))

	for _, task := range tasks {
		summary := Summary{
			CreatedAt: task.CreatedAt.Format(time.RFC3339),
			AreaID:    task.AreaID,
			GoalID:    task.GoalID,
		}

		summary.DeepLink, _ = lunatask.BuildDeepLink(lunatask.ResourceTask, task.ID)

		if task.Status != nil {
			s := string(*task.Status)
			summary.Status = &s
		}

		if task.Priority != nil {
			p := int(*task.Priority)
			summary.Priority = &p
		}

		if task.ScheduledOn != nil {
			s := task.ScheduledOn.Format("2006-01-02")
			summary.ScheduledOn = &s
		}

		summaries = append(summaries, summary)
	}

	return summaries
}

func formatListText(summaries []Summary) string {
	if len(summaries) == 0 {
		return "No tasks found."
	}

	var builder strings.Builder

	builder.WriteString(fmt.Sprintf("Found %d task(s):\n", len(summaries)))

	for _, summary := range summaries {
		status := "unknown"
		if summary.Status != nil {
			status = *summary.Status
		}

		builder.WriteString(fmt.Sprintf("- %s (%s)\n", summary.DeepLink, status))
	}

	builder.WriteString("\nUse show_task for full details.")

	return builder.String()
}
