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

// Package people provides MCP resources for filtered people lists.
package people

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

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

// Resource URIs for people list filters.
const (
	ResourceURIAll = "lunatask://people"
)

// RelationshipTemplate is the URI template for relationship-filtered people resources.
const RelationshipTemplate = "lunatask://people/{relationship}"

// Resource descriptions.
const (
	AllDescription = `All people from relationship tracker.`

	RelationshipDescription = `People filtered by relationship strength.
{relationship} accepts: family, intimate-friends, close-friends, casual-friends,
acquaintances, business-contacts, almost-strangers.`
)

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

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

// personSummary represents a person in list output.
type personSummary struct {
	DeepLink             string  `json:"deep_link"`
	RelationshipStrength *string `json:"relationship_strength,omitempty"`
	CreatedAt            string  `json:"created_at"`
	UpdatedAt            string  `json:"updated_at"`
}

// HandleReadAll handles the all people resource.
func (h *Handler) HandleReadAll(
	ctx context.Context,
	req *mcp.ReadResourceRequest,
) (*mcp.ReadResourceResult, error) {
	return h.handleFiltered(ctx, req, "")
}

// HandleReadByRelationship handles relationship-filtered people resources.
func (h *Handler) HandleReadByRelationship(
	ctx context.Context,
	req *mcp.ReadResourceRequest,
) (*mcp.ReadResourceResult, error) {
	relationship := parseRelationshipURI(req.Params.URI)
	if relationship == "" {
		return nil, fmt.Errorf("invalid URI %q: %w", req.Params.URI, mcp.ResourceNotFoundError(req.Params.URI))
	}

	// Validate relationship strength
	if _, err := lunatask.ParseRelationshipStrength(relationship); err != nil {
		return nil, fmt.Errorf("invalid relationship %q: %w", relationship, mcp.ResourceNotFoundError(req.Params.URI))
	}

	return h.handleFiltered(ctx, req, relationship)
}

func (h *Handler) handleFiltered(
	ctx context.Context,
	req *mcp.ReadResourceRequest,
	relationship string,
) (*mcp.ReadResourceResult, error) {
	people, err := h.client.ListPeople(ctx, nil)
	if err != nil {
		return nil, fmt.Errorf("fetching people: %w", err)
	}

	if relationship != "" {
		people = filterByRelationship(people, relationship)
	}

	summaries := buildSummaries(people)

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

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

func filterByRelationship(people []lunatask.Person, relationship string) []lunatask.Person {
	result := make([]lunatask.Person, 0)

	for _, person := range people {
		if person.RelationshipStrength != nil && string(*person.RelationshipStrength) == relationship {
			result = append(result, person)
		}
	}

	return result
}

func buildSummaries(people []lunatask.Person) []personSummary {
	summaries := make([]personSummary, 0, len(people))

	for _, person := range people {
		summary := personSummary{
			CreatedAt: person.CreatedAt.Format(time.RFC3339),
			UpdatedAt: person.UpdatedAt.Format(time.RFC3339),
		}

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

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

		summaries = append(summaries, summary)
	}

	return summaries
}

// parseRelationshipURI extracts relationship from the URI.
// Example: lunatask://people/close-friends -> close-friends.
func parseRelationshipURI(uri string) string {
	const prefix = "lunatask://people/"

	if !strings.HasPrefix(uri, prefix) {
		return ""
	}

	return strings.TrimPrefix(uri, prefix)
}
