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

// Package timestamp provides an MCP tool for parsing natural language dates.
package timestamp

import (
	"context"
	"fmt"
	"time"

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

// ToolName is the name of this tool.
const ToolName = "get_timestamp"

// ToolDescription describes the tool for LLMs.
const ToolDescription = `Parse natural language dates into RFC3339 timestamps.

Use before passing dates to other tools. Supports PHP strtotime syntax:
relative (+3 days, next Monday), named (March 5), ISO (2024-01-15).
Empty input returns today.`

// ToolAnnotations returns hints about tool behavior.
func ToolAnnotations() *mcp.ToolAnnotations {
	return &mcp.ToolAnnotations{
		ReadOnlyHint:  true,
		OpenWorldHint: ptr(true),
		Title:         "Parse date",
	}
}

func ptr[T any](v T) *T { return &v }

// Input is the input schema for the timestamp tool.
type Input struct {
	Date string `json:"date" jsonschema:"Date/time expression to parse (empty = today)"`
}

// Output is the output schema for the timestamp tool.
type Output struct {
	Timestamp string `json:"timestamp"`
	Date      string `json:"date"`
}

// Handler handles timestamp tool requests.
type Handler struct {
	timezone *time.Location
}

// NewHandler creates a new timestamp handler with the given timezone.
func NewHandler(tz string) *Handler {
	loc, err := time.LoadLocation(tz)
	if err != nil {
		loc = time.UTC
	}

	return &Handler{timezone: loc}
}

// Handle parses a natural language date and returns an RFC3339 timestamp.
func (h *Handler) Handle(
	_ context.Context,
	_ *mcp.CallToolRequest,
	input Input,
) (*mcp.CallToolResult, Output, error) {
	parsed, err := dateutil.ParseInTZ(input.Date, h.timezone)
	if err != nil {
		return &mcp.CallToolResult{
			IsError: true,
			Content: []mcp.Content{
				&mcp.TextContent{Text: err.Error()},
			},
		}, Output{}, nil
	}

	t := parsed.In(h.timezone)
	output := Output{
		Timestamp: t.Format(time.RFC3339),
		Date:      t.Format("2006-01-02"),
	}

	inputDisplay := input.Date
	if inputDisplay == "" {
		inputDisplay = "(empty)"
	}

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{
			Text: fmt.Sprintf("Parsed %q → %s", inputDisplay, output.Timestamp),
		}},
	}, output, nil
}
