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

package note

import (
	"context"
	"fmt"

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

// UpdateToolName is the name of the update note tool.
const UpdateToolName = "update_note"

// UpdateToolDescription describes the update note tool for LLMs.
const UpdateToolDescription = `Updates an existing note in Lunatask.

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

Optional:
- name: New note title
- notebook_id: Move to notebook (UUID from lunatask://notebooks)
- content: Replace content (Markdown)
- date: Note date (YYYY-MM-DD or natural language)

Only provided fields are modified; other fields remain unchanged.`

// UpdateInput is the input schema for updating a note.
type UpdateInput struct {
	ID         string  `json:"id"                    jsonschema:"required"`
	Name       *string `json:"name,omitempty"`
	NotebookID *string `json:"notebook_id,omitempty"`
	Content    *string `json:"content,omitempty"`
	Date       *string `json:"date,omitempty"`
}

// UpdateOutput is the output schema for updating a note.
type UpdateOutput struct {
	DeepLink string `json:"deep_link"`
}

// HandleUpdate updates an existing note.
func (h *Handler) HandleUpdate(
	ctx context.Context,
	_ *mcp.CallToolRequest,
	input UpdateInput,
) (*mcp.CallToolResult, UpdateOutput, error) {
	id, err := parseReference(input.ID)
	if err != nil {
		return shared.ErrorResult(err.Error()), UpdateOutput{}, nil
	}

	if input.NotebookID != nil {
		if err := lunatask.ValidateUUID(*input.NotebookID); err != nil {
			return shared.ErrorResult("invalid notebook_id: expected UUID"), UpdateOutput{}, nil
		}
	}

	builder := h.client.NewNoteUpdate(id)

	if input.Name != nil {
		builder.WithName(*input.Name)
	}

	if input.NotebookID != nil {
		builder.InNotebook(*input.NotebookID)
	}

	if input.Content != nil {
		builder.WithContent(*input.Content)
	}

	if input.Date != nil {
		date, err := dateutil.Parse(*input.Date)
		if err != nil {
			return shared.ErrorResult(err.Error()), UpdateOutput{}, nil
		}

		builder.OnDate(date)
	}

	note, err := builder.Update(ctx)
	if err != nil {
		return shared.ErrorResult(err.Error()), UpdateOutput{}, nil
	}

	deepLink, _ := lunatask.BuildDeepLink(lunatask.ResourceNote, note.ID)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{
			Text: "Note updated: " + deepLink,
		}},
	}, UpdateOutput{DeepLink: deepLink}, nil
}

// parseReference extracts UUID from either a raw UUID or a lunatask:// deep link.
func parseReference(ref string) (string, error) {
	_, id, err := lunatask.ParseReference(ref)
	if err != nil {
		return "", fmt.Errorf("invalid ID: %w", err)
	}

	return id, nil
}
