package dodo_tools

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"sketch.dev/llm"
)

type GetProjectConfigTool struct {
	apiBaseAddress string
	projectId      string
}

func NewGetProjectConfigTool(apiBaseAddress string, projectId string) *llm.Tool {
	tool := &GetProjectConfigTool{
		apiBaseAddress: apiBaseAddress,
		projectId:      projectId,
	}
	return &llm.Tool{
		Name:        "dodo_get_project_config",
		Description: "A tool for getting current state of the infrastructure configuration of a dodo project",
		InputSchema: llm.EmptySchema(),
		Run:         tool.Run,
		EndsTurn:    true,
	}
}

type GetProjectConfigInput struct {
}

type GetProjectConfigOutput struct {
	Config string `json:"config"`
}

func (d *GetProjectConfigTool) Run(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
	resp, err := http.Get(fmt.Sprintf("%s/api/project/%s/config", d.apiBaseAddress, d.projectId))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get project config: %s", string(body))
	}
	output := GetProjectConfigOutput{
		Config: string(body),
	}
	jsonOutput, err := json.Marshal(output)
	if err != nil {
		return nil, err
	}
	return llm.TextContent(string(jsonOutput)), nil
}

type ValidateConfigTool struct {
	apiBaseAddress string
}

const (
	validateConfigSchemaInputSchema = `
{
	"type": "object",
	"properties": {
		"config": {
			"type": "string",
			"description": "The dodo-app configuration to validate"
		}
	},
	"required": ["config"]
}
`
)

func NewValidateConfigTool(apiBaseAddress string) *llm.Tool {
	tool := &ValidateConfigTool{
		apiBaseAddress: apiBaseAddress,
	}
	return &llm.Tool{
		Name:        "dodo_validate_config",
		Description: "A tool for validating the dodo-app configuration",
		InputSchema: llm.MustSchema(validateConfigSchemaInputSchema),
		Run:         tool.Run,
		EndsTurn:    true,
	}
}

type ValidateConfigInput struct {
	Config string `json:"config"`
}

type ValidateConfigOutput struct {
	Success bool `json:"success"`
	Errors  any  `json:"errors,omitempty"`
}

func (d *ValidateConfigTool) Run(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
	var input ValidateConfigInput
	if err := json.Unmarshal(m, &input); err != nil {
		return nil, err
	}
	resp, err := http.Post(fmt.Sprintf("%s/api/validate-config", d.apiBaseAddress), "application/json", bytes.NewBuffer([]byte(input.Config)))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to validate config: %s", string(body))
	}
	var output ValidateConfigOutput
	if err := json.Unmarshal(body, &output); err != nil {
		return nil, err
	}
	jsonOutput, err := json.Marshal(output)
	if err != nil {
		return nil, err
	}
	return llm.TextContent(string(jsonOutput)), nil
}

type DeployProjectTool struct {
	apiBaseAddress string
	projectId      string
}

func NewDeployProjectTool(apiBaseAddress string, projectId string) *llm.Tool {
	tool := &DeployProjectTool{
		apiBaseAddress: apiBaseAddress,
		projectId:      projectId,
	}

	return &llm.Tool{
		Name:        "dodo_deploy_project",
		Description: "A tool for deploying the dodo-app configuration",
		InputSchema: llm.EmptySchema(),
		Run:         tool.Run,
		EndsTurn:    true,
	}
}

type deployProjectReq struct {
	Type string `json:"type"`
}

func (d *DeployProjectTool) Run(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
	req := deployProjectReq{
		Type: "draft",
	}
	jsonReq, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}
	resp, err := http.Post(fmt.Sprintf("%s/api/project/%s/deploy", d.apiBaseAddress, d.projectId), "application/json", bytes.NewBuffer(jsonReq))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to deploy project: %s", string(body))
	}
	return llm.TextContent(string("Project deployed successfully")), nil
}

// Save

type SaveProjectTool struct {
	apiBaseAddress string
	projectId      string
}

const (
	saveProjectSchemaInputSchema = `
{
	"type": "object",
	"properties": {
	}
}
`
)

func NewSaveProjectTool(apiBaseAddress string, projectId string) *llm.Tool {
	tool := &SaveProjectTool{
		apiBaseAddress: apiBaseAddress,
		projectId:      projectId,
	}

	return &llm.Tool{
		Name:        "dodo_save_config",
		Description: "A tool for saving the dodo-app configuration",
		InputSchema: llm.MustSchema(saveProjectSchemaInputSchema),
		Run:         tool.Run,
		EndsTurn:    true,
	}
}

type SaveProjectInput struct {
	Config string `json:"config"`
}

type saveProjectReq struct {
	Type   string         `json:"type"`
	Config map[string]any `json:"config"`
}

func (d *SaveProjectTool) Run(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
	var input SaveProjectInput
	if err := json.Unmarshal(m, &input); err != nil {
		return nil, err
	}
	req := saveProjectReq{
		Type: "config",
	}
	if err := json.Unmarshal([]byte(input.Config), &req.Config); err != nil {
		return nil, err
	}
	jsonReq, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}
	resp, err := http.Post(fmt.Sprintf("%s/api/project/%s/saved", d.apiBaseAddress, d.projectId), "application/json", bytes.NewBuffer(jsonReq))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to save project: %s", string(body))
	}
	return llm.TextContent(string("Project saved successfully")), nil
}

func NewDodoTools(apiBaseAddress string, projectId string) []*llm.Tool {
	return []*llm.Tool{
		NewGetProjectConfigTool(apiBaseAddress, projectId),
		NewValidateConfigTool(apiBaseAddress),
		NewSaveProjectTool(apiBaseAddress, projectId),
		NewDeployProjectTool(apiBaseAddress, projectId),
	}
}
