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

package note

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 notes tool.
const ListToolName = "list_notes"

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

Optional:
- notebook_id: Filter by notebook UUID (from lunatask://notebooks)
- source: Filter by source identifier
- source_id: Filter by source-specific ID

Returns note metadata (IDs, dates, pinned status).
Use lunatask://note/{id} resource for full note details.

Note: Due to end-to-end encryption, note names and content
are not available in the list — only metadata is returned.`

// ListInput is the input schema for listing notes.
type ListInput struct {
	NotebookID *string `json:"notebook_id,omitempty"`
	Source     *string `json:"source,omitempty"`
	SourceID   *string `json:"source_id,omitempty"`
}

// ListNoteItem represents a note in the list output.
type ListNoteItem struct {
	DeepLink   string  `json:"deep_link"`
	NotebookID *string `json:"notebook_id,omitempty"`
	DateOn     *string `json:"date_on,omitempty"`
	Pinned     bool    `json:"pinned"`
	CreatedAt  string  `json:"created_at"`
}

// ListOutput is the output schema for listing notes.
type ListOutput struct {
	Notes []ListNoteItem `json:"notes"`
	Count int            `json:"count"`
}

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

	opts := buildListOptions(input)

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

	if input.NotebookID != nil {
		notes = filterByNotebook(notes, *input.NotebookID)
	}

	items := make([]ListNoteItem, 0, len(notes))

	for _, note := range notes {
		deepLink, _ := lunatask.BuildDeepLink(lunatask.ResourceNote, note.ID)

		item := ListNoteItem{
			DeepLink:   deepLink,
			NotebookID: note.NotebookID,
			Pinned:     note.Pinned,
			CreatedAt:  note.CreatedAt.Format("2006-01-02"),
		}

		if note.DateOn != nil {
			dateStr := note.DateOn.Format("2006-01-02")
			item.DateOn = &dateStr
		}

		items = append(items, item)
	}

	output := ListOutput{
		Notes: items,
		Count: len(items),
	}

	text := formatListText(items, h.notebooks)

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

func buildListOptions(input ListInput) *lunatask.ListNotesOptions {
	if input.Source == nil && input.SourceID == nil {
		return nil
	}

	opts := &lunatask.ListNotesOptions{}

	if input.Source != nil {
		opts.Source = input.Source
	}

	if input.SourceID != nil {
		opts.SourceID = input.SourceID
	}

	return opts
}

func filterByNotebook(notes []lunatask.Note, notebookID string) []lunatask.Note {
	filtered := make([]lunatask.Note, 0, len(notes))

	for _, note := range notes {
		if note.NotebookID != nil && *note.NotebookID == notebookID {
			filtered = append(filtered, note)
		}
	}

	return filtered
}

func formatListText(items []ListNoteItem, notebooks []shared.NotebookProvider) string {
	if len(items) == 0 {
		return "No notes found"
	}

	var text strings.Builder

	text.WriteString(fmt.Sprintf("Found %d note(s):\n", len(items)))

	for _, item := range items {
		text.WriteString("- ")
		text.WriteString(item.DeepLink)

		var details []string

		if item.NotebookID != nil {
			nbName := *item.NotebookID
			for _, nb := range notebooks {
				if nb.ID == *item.NotebookID {
					nbName = nb.Key

					break
				}
			}

			details = append(details, "notebook: "+nbName)
		}

		if item.Pinned {
			details = append(details, "pinned")
		}

		if len(details) > 0 {
			text.WriteString(" (")
			text.WriteString(strings.Join(details, ", "))
			text.WriteString(")")
		}

		text.WriteString("\n")
	}

	text.WriteString("\nUse lunatask://note/{id} resource for full details.")

	return text.String()
}
