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

// Package person provides the MCP resource handler for individual Lunatask people.
package person

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

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

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

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

Due to end-to-end encryption, person name is not available.
Returns metadata including relationship strength and sources.`

// sourceInfo represents a source reference in the response.
type sourceInfo struct {
	Source   string `json:"source"`
	SourceID string `json:"source_id"`
}

// personInfo represents person metadata in the resource response.
type personInfo struct {
	DeepLink             string       `json:"deep_link"`
	RelationshipStrength *string      `json:"relationship_strength,omitempty"`
	Sources              []sourceInfo `json:"sources,omitempty"`
	CreatedAt            string       `json:"created_at"`
	UpdatedAt            string       `json:"updated_at"`
}

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

// NewHandler creates a new person 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 person.
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))
	}

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

	info := buildPersonInfo(person)

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

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

func buildPersonInfo(person *lunatask.Person) personInfo {
	info := personInfo{
		CreatedAt: person.CreatedAt.Format(time.RFC3339),
		UpdatedAt: person.UpdatedAt.Format(time.RFC3339),
	}

	info.DeepLink, _ = lunatask.BuildDeepLink(lunatask.ResourcePerson, person.ID)

	if person.RelationshipStrength != nil {
		s := string(*person.RelationshipStrength)
		info.RelationshipStrength = &s
	}

	if len(person.Sources) > 0 {
		info.Sources = make([]sourceInfo, 0, len(person.Sources))
		for _, src := range person.Sources {
			info.Sources = append(info.Sources, sourceInfo{
				Source:   src.Source,
				SourceID: src.SourceID,
			})
		}
	}

	return info
}
