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

// Package habit provides MCP tools for Lunatask habit operations.
package habit

import (
	"context"

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

// TrackToolName is the name of the track habit tool.
const TrackToolName = "track_habit"

// TrackToolDescription describes the track habit tool for LLMs.
const TrackToolDescription = `Record that a habit was performed.

Use lunatask://habits resource to discover valid habit IDs and config keys.
Tracks for today by default. Idempotent—re-tracking the same date has no effect.`

// TrackToolAnnotations returns hints about tool behavior.
func TrackToolAnnotations() *mcp.ToolAnnotations {
	return &mcp.ToolAnnotations{
		IdempotentHint: true,
		OpenWorldHint:  ptr(true),
		Title:          "Track habit",
	}
}

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

// TrackInput is the input schema for tracking a habit.
type TrackInput struct {
	HabitID     string  `json:"habit_id"               jsonschema:"Habit UUID, lunatask:// deep link, or config key"`
	PerformedOn *string `json:"performed_on,omitempty" jsonschema:"Date performed (strtotime syntax, default: today)"`
}

// TrackOutput is the output schema for tracking a habit.
type TrackOutput struct {
	Success     bool   `json:"success"`
	HabitID     string `json:"habit_id"`
	PerformedOn string `json:"performed_on"`
}

// Handler handles habit-related MCP tool requests.
type Handler struct {
	client *lunatask.Client
	habits []shared.HabitProvider
}

// NewHandler creates a new habit handler.
func NewHandler(accessToken string, habits []shared.HabitProvider) *Handler {
	return &Handler{
		client: lunatask.NewClient(accessToken, lunatask.UserAgent("lune-mcp/1.0")),
		habits: habits,
	}
}

// HandleTrack records a habit activity.
func (h *Handler) HandleTrack(
	ctx context.Context,
	_ *mcp.CallToolRequest,
	input TrackInput,
) (*mcp.CallToolResult, TrackOutput, error) {
	habitID := h.resolveHabitRef(input.HabitID)
	if habitID == "" {
		return shared.ErrorResult("unknown habit: " + input.HabitID), TrackOutput{}, nil
	}

	dateStr := ""
	if input.PerformedOn != nil {
		dateStr = *input.PerformedOn
	}

	performedOn, err := dateutil.Parse(dateStr)
	if err != nil {
		return shared.ErrorResult(err.Error()), TrackOutput{}, nil
	}

	req := &lunatask.TrackHabitActivityRequest{
		PerformedOn: performedOn,
	}

	_, err = h.client.TrackHabitActivity(ctx, habitID, req)
	if err != nil {
		return shared.ErrorResult(err.Error()), TrackOutput{}, nil
	}

	return nil, TrackOutput{
		Success:     true,
		HabitID:     habitID,
		PerformedOn: performedOn.Format("2006-01-02"),
	}, nil
}

// resolveHabitRef resolves a habit reference to a UUID.
// Accepts config key, UUID, or deep link.
func (h *Handler) resolveHabitRef(input string) string {
	// Try UUID or deep link first
	if _, id, err := lunatask.ParseReference(input); err == nil {
		return id
	}

	// Try config key lookup
	for _, habit := range h.habits {
		if habit.Key == input {
			return habit.ID
		}
	}

	return ""
}
