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

package crud

import (
	"context"

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

// DeleteToolName is the name of the consolidated delete tool.
const DeleteToolName = "delete"

// DeleteToolDescription describes the delete tool for LLMs.
const DeleteToolDescription = `Permanently delete an entity from Lunatask.
This action cannot be undone. The entity and its associations are removed.`

// DeleteToolAnnotations returns hints about tool behavior.
func DeleteToolAnnotations() *mcp.ToolAnnotations {
	return &mcp.ToolAnnotations{
		DestructiveHint: ptr(true),
		OpenWorldHint:   ptr(true),
		Title:           "Delete entity",
	}
}

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

// toAnyStrings converts a slice of string-based types to []any for JSON schema enums.
func toAnyStrings[T ~string](slice []T) []any {
	result := make([]any, len(slice))
	for i, v := range slice {
		result[i] = string(v)
	}

	return result
}

// prioritiesToAny converts priorities to their string representations for JSON schema enums.
func prioritiesToAny(priorities []lunatask.Priority) []any {
	result := make([]any, len(priorities))
	for i := range priorities {
		result[i] = priorities[i].String()
	}

	return result
}

// DeleteInputSchema returns a custom schema with enum constraints.
func DeleteInputSchema() *jsonschema.Schema {
	schema, _ := jsonschema.For[DeleteInput](nil)

	schema.Properties["entity"].Enum = []any{
		EntityTask, EntityNote, EntityPerson,
	}

	return schema
}

// DeleteInput is the input schema for the consolidated delete tool.
type DeleteInput struct {
	Entity string `json:"entity" jsonschema:"Entity type to delete"`
	ID     string `json:"id"     jsonschema:"UUID or lunatask:// deep link"`
}

// DeleteOutput is the output schema for the consolidated delete tool.
type DeleteOutput struct {
	Entity   string `json:"entity"`
	DeepLink string `json:"deep_link"`
	Success  bool   `json:"success"`
}

// HandleDelete deletes an entity based on the entity type.
func (h *Handler) HandleDelete(
	ctx context.Context,
	_ *mcp.CallToolRequest,
	input DeleteInput,
) (*mcp.CallToolResult, DeleteOutput, error) {
	switch input.Entity {
	case EntityTask:
		return h.deleteTask(ctx, input)
	case EntityNote:
		return h.deleteNote(ctx, input)
	case EntityPerson:
		return h.deletePerson(ctx, input)
	default:
		return shared.ErrorResult("invalid entity: must be task, note, or person"),
			DeleteOutput{Entity: input.Entity}, nil
	}
}

func (h *Handler) deleteTask(
	ctx context.Context,
	input DeleteInput,
) (*mcp.CallToolResult, DeleteOutput, error) {
	_, id, err := lunatask.ParseReference(input.ID)
	if err != nil {
		return shared.ErrorResult("invalid ID: expected UUID or lunatask:// deep link"),
			DeleteOutput{Entity: input.Entity}, nil
	}

	deepLink, _ := lunatask.BuildDeepLink(lunatask.ResourceTask, id)

	if _, err := h.client.DeleteTask(ctx, id); err != nil {
		return shared.ErrorResult(err.Error()), DeleteOutput{Entity: input.Entity}, nil
	}

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{
			Text: "Task deleted: " + deepLink,
		}},
	}, DeleteOutput{Entity: input.Entity, DeepLink: deepLink, Success: true}, nil
}

func (h *Handler) deleteNote(
	ctx context.Context,
	input DeleteInput,
) (*mcp.CallToolResult, DeleteOutput, error) {
	_, id, err := lunatask.ParseReference(input.ID)
	if err != nil {
		return shared.ErrorResult("invalid ID: expected UUID or lunatask:// deep link"),
			DeleteOutput{Entity: input.Entity}, nil
	}

	note, err := h.client.DeleteNote(ctx, id)
	if err != nil {
		return shared.ErrorResult(err.Error()), DeleteOutput{Entity: input.Entity}, nil
	}

	deepLink, _ := lunatask.BuildDeepLink(lunatask.ResourceNote, note.ID)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{
			Text: "Note deleted: " + deepLink,
		}},
	}, DeleteOutput{Entity: input.Entity, DeepLink: deepLink, Success: true}, nil
}

func (h *Handler) deletePerson(
	ctx context.Context,
	input DeleteInput,
) (*mcp.CallToolResult, DeleteOutput, error) {
	_, id, err := lunatask.ParseReference(input.ID)
	if err != nil {
		return shared.ErrorResult("invalid ID: expected UUID or lunatask:// deep link"),
			DeleteOutput{Entity: input.Entity}, nil
	}

	person, err := h.client.DeletePerson(ctx, id)
	if err != nil {
		return shared.ErrorResult(err.Error()), DeleteOutput{Entity: input.Entity}, nil
	}

	deepLink, _ := lunatask.BuildDeepLink(lunatask.ResourcePerson, person.ID)

	return &mcp.CallToolResult{
		Content: []mcp.Content{&mcp.TextContent{
			Text: "Person deleted: " + deepLink,
		}},
	}, DeleteOutput{Entity: input.Entity, DeepLink: deepLink, Success: true}, nil
}
