package tools

import (
	"context"
	"strings"

	"github.com/google/uuid"
	"github.com/modelcontextprotocol/go-sdk/mcp"

	"git.warky.dev/wdevs/amcs/internal/ai"
	"git.warky.dev/wdevs/amcs/internal/config"
	"git.warky.dev/wdevs/amcs/internal/metadata"
	"git.warky.dev/wdevs/amcs/internal/session"
	"git.warky.dev/wdevs/amcs/internal/store"
	thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)

// EmbeddingQueuer queues a thought for background embedding generation.
type EmbeddingQueuer interface {
	QueueThought(ctx context.Context, id uuid.UUID, content string)
}

// MetadataQueuer queues a thought for background metadata retry. Both
// MetadataRetryer and EnrichmentRetryer satisfy this.
type MetadataQueuer interface {
	QueueThought(id uuid.UUID)
}

type CaptureTool struct {
	store        *store.DB
	embeddings   *ai.EmbeddingRunner
	capture      config.CaptureConfig
	sessions     *session.ActiveProjects
	retryer      MetadataQueuer
	embedRetryer EmbeddingQueuer
}

type CaptureInput struct {
	Content string `json:"content" jsonschema:"the thought or note to capture"`
	Project string `json:"project,omitempty" jsonschema:"optional project name or id to associate with the thought"`
}

type CaptureOutput struct {
	Thought thoughttypes.Thought `json:"thought"`
}

func NewCaptureTool(db *store.DB, embeddings *ai.EmbeddingRunner, capture config.CaptureConfig, sessions *session.ActiveProjects, retryer MetadataQueuer, embedRetryer EmbeddingQueuer) *CaptureTool {
	return &CaptureTool{store: db, embeddings: embeddings, capture: capture, sessions: sessions, retryer: retryer, embedRetryer: embedRetryer}
}

func (t *CaptureTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in CaptureInput) (*mcp.CallToolResult, CaptureOutput, error) {
	content := strings.TrimSpace(in.Content)
	if content == "" {
		return nil, CaptureOutput{}, errRequiredField("content")
	}

	project, err := resolveProject(ctx, t.store, t.sessions, req, in.Project, false)
	if err != nil {
		return nil, CaptureOutput{}, err
	}

	rawMetadata := metadata.Fallback(t.capture)
	rawMetadata.MetadataStatus = metadata.MetadataStatusPending
	thought := thoughttypes.Thought{
		Content:  content,
		Metadata: rawMetadata,
	}
	if project != nil {
		thought.ProjectID = &project.ID
	}

	created, err := t.store.InsertThought(ctx, thought, t.embeddings.PrimaryModel())
	if err != nil {
		return nil, CaptureOutput{}, err
	}
	if project != nil {
		_ = t.store.TouchProject(ctx, project.ID)
	}

	if t.retryer != nil {
		t.retryer.QueueThought(created.ID)
	}
	if t.embedRetryer != nil {
		t.embedRetryer.QueueThought(ctx, created.ID, content)
	}

	return nil, CaptureOutput{Thought: created}, nil
}
