package loop

import (
	_ "embed"
	"encoding/json"
	"fmt"
	"sync"

	"dodo.cloud/neo/tools"

	"github.com/anthropics/anthropic-sdk-go"
	"github.com/invopop/jsonschema"
)

//go:embed CONVERSATION_RULES.md
var systemPrompt string

var todo *ToDo

func Run(pr PromptReader, client *Client, tools tools.Registry) error {
	RegisterToDoTools(tools)
	fmt.Printf("YOU: ")
	prompt, err := pr.Read()
	if err != nil {
		return err
	}
	todo = &ToDo{}
	todo.ID = "1"
	todo.Title = prompt
	todo.AssignedTo = "assistant"
	agents := []Agent{
		&UserAgent{pr},
		&AnthropicAgent{pr, tools, client.c},
	}
	var wg sync.WaitGroup
	for _, a := range agents {
		wg.Add(1)
		go func() {
			if err := a.Run(todo); err != nil {
				panic(err)
			}
			wg.Done()
		}()
	}
	wg.Wait()
	return nil
}

func pickToDoItem(todo *ToDo) *ToDo {
	if todo.Done {
		return nil
	}
	for _, i := range todo.Items {
		if ret := pickToDoItem(i); ret != nil {
			return ret
		}
	}
	return todo
}

func findItemByID(todo *ToDo, id string) *ToDo {
	if todo.ID == id {
		return todo
	}
	for _, i := range todo.Items {
		if ret := findItemByID(i, id); ret != nil {
			return ret
		}
	}
	return nil
}

type ToDoSubItem struct {
	Title       string `json:"title" jsonschema:"title=title,description=high level title of the TODO item,required"`
	Description string `json:"description" jsonschema:"title=description,description=detailed description what this TODO item is about"`
	AssignedTo  string `json:"assignedTo" jsonschema:"title=assigned to,description=name of the person who shall work on this utem"`
}

type ToDoItem struct {
	ParentID    string        `json:"parentId" jsonschema:"title=parent item id,description=ID of the parent TODO item this one shall be added to as a sub-item"`
	Title       string        `json:"title" jsonschema:"title=title,description=high level title of the TODO item,required"`
	Description string        `json:"description" jsonschema:"title=description,description=detailed description what this TODO item is about"`
	AssignedTo  string        `json:"assignedTo" jsonschema:"title=assigned to,description=name of the person who shall work on this utem"`
	Items       []ToDoSubItem `json:"items" jsonschema:"title=sub items,description:array of sub-items"`
	Parallel    bool          `json:"parallel" jsonschema:"title=parallel,description=if true sub-items may be worked on in parallel and there is no depencency between them, otherwise they shall be worked on sequentially"`
}

type ToDoAddItemArgs struct {
	Items []ToDoItem `json:"items" jsonschema:"title=items,description="items to add to the TODO list,required""`
}

func ToDoAddItem(args ToDoAddItemArgs) (string, error) {
	for _, td := range args.Items {
		item := findItemByID(todo, td.ParentID)
		if item == nil {
			return "error", fmt.Errorf("TODO item with given id not found: %s", td.ParentID)
		}
		id := fmt.Sprintf("%s.%d", item.ID, len(item.Items)+1)
		item.Items = append(item.Items, &ToDo{
			ID:          id,
			Title:       td.Title,
			Description: td.Description,
			AssignedTo:  td.AssignedTo,
			Parallel:    td.Parallel,
		})
		ti := item.Items[len(item.Items)-1]
		for _, s := range td.Items {
			sid := fmt.Sprintf("%s.%d", id, len(ti.Items)+1)
			ti.Items = append(ti.Items, &ToDo{
				ID:          sid,
				Title:       s.Title,
				Description: s.Description,
				AssignedTo:  s.AssignedTo,
			})
		}
	}
	return "done", nil
}

type ToDoMarkItemDoneArgs struct {
	ID      string `json:"id" jsonschema:"title=id,description=id of the TODO item to mark as DONE,required"`
	Summary string `json:"summary" jsonschem:"title=summary,description=detailed summary of current item and all of it's sub-item trees.,required"`
}

func ToDoMarkItemDone(args ToDoMarkItemDoneArgs) (string, error) {
	item := findItemByID(todo, args.ID)
	if item == nil {
		return "error", fmt.Errorf("TODO item with given id not found: %s", args.ID)
	}
	item.Done = true
	item.Summary = args.Summary
	return "done", nil
}

type ToDoItemAddCommentArgs struct {
	ID       string `json:"id" jsonschema:"title=id,description=id of the TODO item to add comment to,required"`
	Comment  string `json:"comment" jsonschema:"title=comment,description=actual comment text,required"`
	AssignTo string `json:"assignTo" jsonschema:"title=assigned to,description=name of the person who shall be assigned to TODO item with given ID, if empty assignment does not chage"`
}

func ToDoItemAddComment(args ToDoItemAddCommentArgs) (string, error) {
	item := findItemByID(todo, args.ID)
	if item == nil {
		return "error", fmt.Errorf("TODO item with given id not found: %s", args.ID)
	}
	if len(item.Discussion) == 0 {
		return "error", fmt.Errorf("You shall never initiate a discussion, if you want to clarify something create a TODO item for it.")
	}
	item.Discussion = append(item.Discussion, Comment{
		Author:  "assistant",
		Comment: args.Comment,
	})
	if args.AssignTo != "" {
		item.AssignedTo = args.AssignTo
	}
	return "done", nil
}

func RegisterToDoTools(reg tools.Registry) {
	reg.Add(tools.NewFuncTool("todo_item_add", ToDoAddItem, "Add new ToDo item."))
	reg.Add(tools.NewFuncTool("todo_item_mark_done", ToDoMarkItemDone, "Marks ToDo item with given ID as done."))
	reg.Add(tools.NewFuncTool("todo_item_add_comment", ToDoItemAddComment, "Adds discussion comment to given ToDo item"))
}

func GetToolSchema(schema *jsonschema.Schema) (anthropic.ToolInputSchemaParam, error) {
	schemaBytes, err := json.Marshal(schema)
	if err != nil {
		return anthropic.ToolInputSchemaParam{}, err
	}
	var schemaMap map[string]any
	if err := json.Unmarshal(schemaBytes, &schemaMap); err != nil {
		return anthropic.ToolInputSchemaParam{}, err
	}

	inputSchema, err := parseSchemaMap(schemaMap)
	if err != nil {
		return anthropic.ToolInputSchemaParam{}, err
	}
	return inputSchema, nil
}

func parseSchemaMap(s map[string]any) (anthropic.ToolInputSchemaParam, error) {
	bytes, err := json.Marshal(s)
	if err != nil {
		return anthropic.ToolInputSchemaParam{}, fmt.Errorf("failed to marshal schema: %w", err)
	}

	var schema anthropic.ToolInputSchemaParam
	if err := json.Unmarshal(bytes, &schema); err != nil {
		return anthropic.ToolInputSchemaParam{}, fmt.Errorf("failed to unmarshal schema: %w", err)
	}

	return schema, nil
}
