package tools

import (
	"context"
	"strings"

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

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

type ProjectsTool struct {
	store    *store.DB
	sessions *session.ActiveProjects
}

type CreateProjectInput struct {
	Name        string `json:"name" jsonschema:"the unique project name"`
	Description string `json:"description,omitempty" jsonschema:"optional project description"`
}

type CreateProjectOutput struct {
	Project thoughttypes.Project `json:"project"`
}

type ListProjectsInput struct{}

type ListProjectsOutput struct {
	Projects []thoughttypes.ProjectSummary `json:"projects"`
}

type SetActiveProjectInput struct {
	Project string `json:"project" jsonschema:"project name or id"`
}

type SetActiveProjectOutput struct {
	Project thoughttypes.Project `json:"project"`
}

type GetActiveProjectInput struct{}

type GetActiveProjectOutput struct {
	Project *thoughttypes.Project `json:"project,omitempty"`
}

func NewProjectsTool(db *store.DB, sessions *session.ActiveProjects) *ProjectsTool {
	return &ProjectsTool{store: db, sessions: sessions}
}

func (t *ProjectsTool) Create(ctx context.Context, _ *mcp.CallToolRequest, in CreateProjectInput) (*mcp.CallToolResult, CreateProjectOutput, error) {
	name := strings.TrimSpace(in.Name)
	if name == "" {
		return nil, CreateProjectOutput{}, errRequiredField("name")
	}
	project, err := t.store.CreateProject(ctx, name, strings.TrimSpace(in.Description))
	if err != nil {
		return nil, CreateProjectOutput{}, err
	}
	return nil, CreateProjectOutput{Project: project}, nil
}

func (t *ProjectsTool) List(ctx context.Context, _ *mcp.CallToolRequest, _ ListProjectsInput) (*mcp.CallToolResult, ListProjectsOutput, error) {
	projects, err := t.store.ListProjects(ctx)
	if err != nil {
		return nil, ListProjectsOutput{}, err
	}
	return nil, ListProjectsOutput{Projects: projects}, nil
}

func (t *ProjectsTool) SetActive(ctx context.Context, req *mcp.CallToolRequest, in SetActiveProjectInput) (*mcp.CallToolResult, SetActiveProjectOutput, error) {
	sid, err := sessionID(req)
	if err != nil {
		return nil, SetActiveProjectOutput{}, err
	}
	project, err := resolveProject(ctx, t.store, t.sessions, req, in.Project, true)
	if err != nil {
		return nil, SetActiveProjectOutput{}, err
	}
	t.sessions.Set(sid, project.ID)
	_ = t.store.TouchProject(ctx, project.NumericID)
	return nil, SetActiveProjectOutput{Project: *project}, nil
}

func (t *ProjectsTool) GetActive(ctx context.Context, req *mcp.CallToolRequest, _ GetActiveProjectInput) (*mcp.CallToolResult, GetActiveProjectOutput, error) {
	project, err := resolveProject(ctx, t.store, t.sessions, req, "", false)
	if err != nil {
		return nil, GetActiveProjectOutput{}, err
	}
	return nil, GetActiveProjectOutput{Project: project}, nil
}
