package tools

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"git.yeij.top/AskaEth/Cyrene/ai-core/internal/host"
)

// HostExecTool allows the AI to execute commands in a sandboxed environment.
type HostExecTool struct {
	manager *host.Manager
}

// NewHostExecTool creates a new host exec tool.
func NewHostExecTool(manager *host.Manager) *HostExecTool {
	return &HostExecTool{manager: manager}
}

func (t *HostExecTool) Definition() ToolDefinition {
	return ToolDefinition{
		Name:        "host_exec",
		Description: "在安全沙箱中执行系统命令。支持运行脚本、编译代码、管理文件等操作。超时默认30秒，最大300秒。",
		Parameters: map[string]interface{}{
			"type": "object",
			"properties": map[string]interface{}{
				"command": map[string]interface{}{
					"type":        "string",
					"description": "要执行的命令，例如 'dir C:\\Projects' 或 'python script.py'",
				},
				"work_dir": map[string]interface{}{
					"type":        "string",
					"description": "工作目录。不指定则使用默认目录。",
				},
				"timeout_sec": map[string]interface{}{
					"type":        "integer",
					"description": "超时时间（秒），默认30秒，最大300秒。",
				},
			},
			"required": []string{"command"},
		},
	}
}

func (t *HostExecTool) Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error) {
	cmd, _ := args["command"].(string)
	if cmd == "" {
		return &ToolResult{
			ToolName: "host_exec",
			Success:  false,
			Error:    "command 参数不能为空",
		}, nil
	}

	workDir, _ := args["work_dir"].(string)
	timeoutSec := 30
	if v, ok := args["timeout_sec"].(float64); ok {
		timeoutSec = int(v)
	}
	timeout := time.Duration(timeoutSec) * time.Second

	result, err := t.manager.Exec(ctx, cmd, workDir, timeout)
	if err != nil && result == nil {
		return &ToolResult{
			ToolName: "host_exec",
			Success:  false,
			Error:    err.Error(),
		}, nil
	}

	data, _ := json.Marshal(map[string]interface{}{
		"command":   cmd,
		"exit_code": result.ExitCode,
		"duration":  result.Duration,
		"timed_out": result.TimedOut,
		"stdout":    result.Stdout,
		"stderr":    result.Stderr,
	})

	success := result.ExitCode == 0 && !result.TimedOut
	return &ToolResult{
		ToolName: "host_exec",
		Success:  success,
		Data:     string(data),
	}, nil
}

// HostFileTool provides controlled file system access.
type HostFileTool struct {
	manager *host.Manager
}

// NewHostFileTool creates a new host file tool.
func NewHostFileTool(manager *host.Manager) *HostFileTool {
	return &HostFileTool{manager: manager}
}

func (t *HostFileTool) Definition() ToolDefinition {
	return ToolDefinition{
		Name:        "host_file",
		Description: "在允许的目录中读取、写入或列出文件。支持 read/write/list 三种操作。",
		Parameters: map[string]interface{}{
			"type": "object",
			"properties": map[string]interface{}{
				"action": map[string]interface{}{
					"type":        "string",
					"description": "操作类型: read, write, list",
					"enum":        []string{"read", "write", "list"},
				},
				"path": map[string]interface{}{
					"type":        "string",
					"description": "文件或目录路径",
				},
				"content": map[string]interface{}{
					"type":        "string",
					"description": "写入内容 (仅 write 操作需要)",
				},
			},
			"required": []string{"action", "path"},
		},
	}
}

func (t *HostFileTool) Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error) {
	action, _ := args["action"].(string)
	path, _ := args["path"].(string)
	if action == "" || path == "" {
		return &ToolResult{
			ToolName: "host_file",
			Success:  false,
			Error:    "action 和 path 参数不能为空",
		}, nil
	}

	switch action {
	case "read":
		content, err := t.manager.ReadFile(path, 1024*1024)
		if err != nil {
			return &ToolResult{ToolName: "host_file", Success: false, Error: err.Error()}, nil
		}
		data, _ := json.Marshal(map[string]interface{}{
			"path":    path,
			"content": content,
			"size":    len(content),
		})
		return &ToolResult{ToolName: "host_file", Success: true, Data: string(data)}, nil

	case "write":
		content, _ := args["content"].(string)
		if err := t.manager.WriteFile(path, content, 1024*1024); err != nil {
			return &ToolResult{ToolName: "host_file", Success: false, Error: err.Error()}, nil
		}
		data, _ := json.Marshal(map[string]interface{}{
			"path":    path,
			"written": len(content),
			"status":  "ok",
		})
		return &ToolResult{ToolName: "host_file", Success: true, Data: string(data)}, nil

	case "list":
		entries, err := t.manager.ListDir(path)
		if err != nil {
			return &ToolResult{ToolName: "host_file", Success: false, Error: err.Error()}, nil
		}
		data, _ := json.Marshal(map[string]interface{}{
			"path":    path,
			"entries": entries,
			"count":   len(entries),
		})
		return &ToolResult{ToolName: "host_file", Success: true, Data: string(data)}, nil

	default:
		return &ToolResult{ToolName: "host_file", Success: false, Error: fmt.Sprintf("不支持的操作: %s", action)}, nil
	}
}

// HostSystemTool provides system information.
type HostSystemTool struct {
	manager *host.Manager
}

// NewHostSystemTool creates a new system info tool.
func NewHostSystemTool(manager *host.Manager) *HostSystemTool {
	return &HostSystemTool{manager: manager}
}

func (t *HostSystemTool) Definition() ToolDefinition {
	return ToolDefinition{
		Name:        "host_system",
		Description: "获取主机系统信息，包括操作系统、CPU、内存等。",
		Parameters: map[string]interface{}{
			"type": "object",
			"properties": map[string]interface{}{
				"query": map[string]interface{}{
					"type":        "string",
					"description": "查询类型: info(完整信息), memory(内存), cpu(CPU), disk(磁盘)",
					"enum":        []string{"info", "memory", "cpu", "disk"},
				},
			},
		},
	}
}

func (t *HostSystemTool) Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error) {
	info := t.manager.SystemInfo()
	data, _ := json.Marshal(info)
	return &ToolResult{
		ToolName: "host_system",
		Success:  true,
		Data:     string(data),
	}, nil
}
