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

package note

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

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

// ShowToolName is the name of the show note tool.
const ShowToolName = "show_note"

// ShowToolDescription describes the show note tool for LLMs.
const ShowToolDescription = `Shows metadata for a specific note from Lunatask.

Required:
- id: Note UUID or lunatask:// deep link

Note: Due to end-to-end encryption, note title and content are not available.
Only metadata (notebook, date, pinned status, sources) is returned.`

// ShowInput is the input schema for showing a note.
type ShowInput struct {
	ID string `json:"id" jsonschema:"required"`
}

// ShowSource represents a source reference in the output.
type ShowSource struct {
	Source   string `json:"source"`
	SourceID string `json:"source_id"`
}

// ShowOutput is the output schema for showing a note.
type ShowOutput struct {
	DeepLink   string       `json:"deep_link"`
	NotebookID *string      `json:"notebook_id,omitempty"`
	DateOn     *string      `json:"date_on,omitempty"`
	Pinned     bool         `json:"pinned"`
	Sources    []ShowSource `json:"sources,omitempty"`
	CreatedAt  string       `json:"created_at"`
	UpdatedAt  string       `json:"updated_at"`
}

// HandleShow shows a note's details.
func (h *Handler) HandleShow(
	ctx context.Context,
	_ *mcp.CallToolRequest,
	input ShowInput,
) (*mcp.CallToolResult, ShowOutput, error) {
	_, id, err := lunatask.ParseReference(input.ID)
	if err != nil {
		return shared.ErrorResult("invalid ID: expected UUID or lunatask:// deep link"), ShowOutput{}, nil
	}

	note, err := h.client.GetNote(ctx, id)
	if err != nil {
		return shared.ErrorResult(err.Error()), ShowOutput{}, nil
	}

	output := buildShowOutput(note)
	text := formatNoteShowText(output, h.notebooks)

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

func buildShowOutput(note *lunatask.Note) ShowOutput {
	output := ShowOutput{
		NotebookID: note.NotebookID,
		Pinned:     note.Pinned,
		CreatedAt:  note.CreatedAt.Format(time.RFC3339),
		UpdatedAt:  note.UpdatedAt.Format(time.RFC3339),
	}

	output.DeepLink, _ = lunatask.BuildDeepLink(lunatask.ResourceNote, note.ID)

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

	if len(note.Sources) > 0 {
		output.Sources = make([]ShowSource, 0, len(note.Sources))
		for _, src := range note.Sources {
			output.Sources = append(output.Sources, ShowSource{
				Source:   src.Source,
				SourceID: src.SourceID,
			})
		}
	}

	return output
}

func formatNoteShowText(output ShowOutput, notebooks []shared.NotebookProvider) string {
	var builder strings.Builder

	builder.WriteString(fmt.Sprintf("Note: %s\n", output.DeepLink))

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

				break
			}
		}

		builder.WriteString(fmt.Sprintf("Notebook: %s\n", nbName))
	}

	if output.DateOn != nil {
		builder.WriteString(fmt.Sprintf("Date: %s\n", *output.DateOn))
	}

	if output.Pinned {
		builder.WriteString("Pinned: yes\n")
	}

	if len(output.Sources) > 0 {
		builder.WriteString("Sources:\n")

		for _, src := range output.Sources {
			builder.WriteString(fmt.Sprintf("  - %s: %s\n", src.Source, src.SourceID))
		}
	}

	builder.WriteString(fmt.Sprintf("Created: %s\n", output.CreatedAt))
	builder.WriteString("Updated: " + output.UpdatedAt)

	return builder.String()
}
