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

package task

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 task tool.
const ShowToolName = "show_task"

// ShowToolDescription describes the show task tool for LLMs.
const ShowToolDescription = `Shows details of a specific task from Lunatask.

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

Note: Due to end-to-end encryption, task name and note content are not available.
Only metadata (ID, status, dates, priority, etc.) is returned.`

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

// ShowOutput is the output schema for showing a task.
type ShowOutput struct {
	DeepLink    string  `json:"deep_link"`
	Status      *string `json:"status,omitempty"`
	Priority    *int    `json:"priority,omitempty"`
	Estimate    *int    `json:"estimate,omitempty"`
	ScheduledOn *string `json:"scheduled_on,omitempty"`
	CompletedAt *string `json:"completed_at,omitempty"`
	CreatedAt   string  `json:"created_at"`
	UpdatedAt   string  `json:"updated_at"`
	AreaID      *string `json:"area_id,omitempty"`
	GoalID      *string `json:"goal_id,omitempty"`
	Important   *bool   `json:"important,omitempty"`
	Urgent      *bool   `json:"urgent,omitempty"`
}

// HandleShow shows a task'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
	}

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

	output := ShowOutput{
		CreatedAt: task.CreatedAt.Format(time.RFC3339),
		UpdatedAt: task.UpdatedAt.Format(time.RFC3339),
		AreaID:    task.AreaID,
		GoalID:    task.GoalID,
	}

	output.DeepLink, _ = lunatask.BuildDeepLink(lunatask.ResourceTask, task.ID)

	if task.Status != nil {
		s := string(*task.Status)
		output.Status = &s
	}

	if task.Priority != nil {
		p := int(*task.Priority)
		output.Priority = &p
	}

	if task.Estimate != nil {
		output.Estimate = task.Estimate
	}

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

	if task.CompletedAt != nil {
		s := task.CompletedAt.Format(time.RFC3339)
		output.CompletedAt = &s
	}

	if task.Eisenhower != nil {
		important := task.Eisenhower.IsImportant()
		urgent := task.Eisenhower.IsUrgent()
		output.Important = &important
		output.Urgent = &urgent
	}

	text := formatShowText(output)

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

func formatShowText(output ShowOutput) string {
	var builder strings.Builder

	builder.WriteString(fmt.Sprintf("Task: %s\n", output.DeepLink))
	writeOptionalField(&builder, "Status", output.Status)
	writeOptionalIntField(&builder, "Priority", output.Priority)
	writeOptionalField(&builder, "Scheduled", output.ScheduledOn)
	writeOptionalMinutesField(&builder, "Estimate", output.Estimate)
	writeEisenhowerField(&builder, output.Important, output.Urgent)
	builder.WriteString(fmt.Sprintf("Created: %s\n", output.CreatedAt))
	builder.WriteString("Updated: " + output.UpdatedAt)
	writeOptionalField(&builder, "\nCompleted", output.CompletedAt)

	return builder.String()
}

func writeOptionalField(builder *strings.Builder, label string, value *string) {
	if value != nil {
		fmt.Fprintf(builder, "%s: %s\n", label, *value)
	}
}

func writeOptionalIntField(builder *strings.Builder, label string, value *int) {
	if value != nil {
		fmt.Fprintf(builder, "%s: %d\n", label, *value)
	}
}

func writeOptionalMinutesField(builder *strings.Builder, label string, value *int) {
	if value != nil {
		fmt.Fprintf(builder, "%s: %d min\n", label, *value)
	}
}

func writeEisenhowerField(builder *strings.Builder, important, urgent *bool) {
	var parts []string

	if important != nil && *important {
		parts = append(parts, "important")
	}

	if urgent != nil && *urgent {
		parts = append(parts, "urgent")
	}

	if len(parts) > 0 {
		fmt.Fprintf(builder, "Eisenhower: %s\n", strings.Join(parts, ", "))
	}
}
