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

// Package task provides the MCP resource handler for individual Lunatask tasks.
package task

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

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

// ResourceTemplate is the URI template for task resources.
const ResourceTemplate = "lunatask://task/{id}"

// ResourceDescription describes the task resource for LLMs.
const ResourceDescription = `Reads metadata for a specific Lunatask task by ID or deep link.

Due to end-to-end encryption, task name and note content are not available.
Returns metadata including status, priority, dates, area, and goal.

Use list_tasks tool to discover task IDs, then read individual tasks here.`

// taskInfo represents task metadata in the resource response.
type taskInfo 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"`
}

// Handler handles task resource requests.
type Handler struct {
	client *lunatask.Client
}

// NewHandler creates a new task resource handler.
func NewHandler(accessToken string) *Handler {
	return &Handler{
		client: lunatask.NewClient(accessToken, lunatask.UserAgent("lune-mcp/1.0")),
	}
}

// HandleRead returns metadata for a specific task.
func (h *Handler) HandleRead(
	ctx context.Context,
	req *mcp.ReadResourceRequest,
) (*mcp.ReadResourceResult, error) {
	_, id, err := lunatask.ParseReference(req.Params.URI)
	if err != nil {
		return nil, fmt.Errorf("invalid URI %q: %w", req.Params.URI, mcp.ResourceNotFoundError(req.Params.URI))
	}

	task, err := h.client.GetTask(ctx, id)
	if err != nil {
		return nil, fmt.Errorf("fetching task: %w", err)
	}

	info := buildTaskInfo(task)

	data, err := json.MarshalIndent(info, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("marshaling task: %w", err)
	}

	return &mcp.ReadResourceResult{
		Contents: []*mcp.ResourceContents{{
			URI:      req.Params.URI,
			MIMEType: "application/json",
			Text:     string(data),
		}},
	}, nil
}

func buildTaskInfo(task *lunatask.Task) taskInfo {
	info := taskInfo{
		CreatedAt: task.CreatedAt.Format(time.RFC3339),
		UpdatedAt: task.UpdatedAt.Format(time.RFC3339),
		AreaID:    task.AreaID,
		GoalID:    task.GoalID,
	}

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

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

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

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

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

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

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

	return info
}
