package dodo_tools

import (
	"context"
	"bytes"
	"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) {
	fmt.Printf("%s\n", string(m))
	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
}

const (
	deployProjectSchemaInputSchema = `
{
	"type": "object",
	"properties": {
		"config": {
			"type": "string",
			"description": "Serialized dodo-app configuration to deploy"
		}
	}
}
`
)

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.MustSchema(deployProjectSchemaInputSchema),
		Run:         tool.Run,
		EndsTurn:    true,
	}
}

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

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

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

func (d *DeployProjectTool) Run(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
	var input DeployProjectInput
	if err := json.Unmarshal(m, &input); err != nil {
		return nil, err
	}
	req := deployProjectReq{}
	if err := json.Unmarshal([]byte(input.Config), &req.Config); err != nil {
		return nil, err
	}
	fmt.Printf("### %+v\n", req)
	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
}

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