package tools

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

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

// OSExecTool allows the AI to execute arbitrary commands in a full OS
// environment (WSL or Docker container). Unlike host_exec which runs in
// a restricted sandbox, this provides unrestricted OS access.
type OSExecTool struct {
	manager *host.Manager
}

// NewOSExecTool creates a new OS exec tool for full OS command execution.
func NewOSExecTool(manager *host.Manager) *OSExecTool {
	return &OSExecTool{manager: manager}
}

func (t *OSExecTool) Definition() ToolDefinition {
	return ToolDefinition{
		Name:        "os_exec",
		Description: "在完整的操作系统环境（WSL/Docker容器）中执行任意命令。适用于复杂操作：安装软件包、编译大型项目、运行脚本、管理服务等。拥有完整的Linux系统权限，无命令限制。日常简单操作请使用 host_exec。",
		Parameters: map[string]interface{}{
			"type": "object",
			"properties": map[string]interface{}{
				"command": map[string]interface{}{
					"type":        "string",
					"description": "要执行的命令，例如 'pip install pandas && python analyze.py' 或 'apt-get update && apt-get install -y ffmpeg'",
				},
				"work_dir": map[string]interface{}{
					"type":        "string",
					"description": "工作目录。不指定则使用默认目录。",
				},
				"timeout_sec": map[string]interface{}{
					"type":        "integer",
					"description": "超时时间（秒），默认30秒，最大300秒。复杂任务请设置更长的超时。",
				},
			},
			"required": []string{"command"},
		},
	}
}

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

	workDir, _ := args["work_dir"].(string)
	timeoutSec := 60 // Default longer timeout for complex operations
	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: "os_exec",
			Success:  false,
			Error:    err.Error(),
		}, nil
	}

	data, _ := json.Marshal(map[string]interface{}{
		"command":   cmd,
		"backend":   t.manager.BackendName(),
		"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: "os_exec",
		Success:  success,
		Data:     string(data),
	}, nil
}

// OSFileTool provides unrestricted file system access within the OS environment.
type OSFileTool struct {
	manager *host.Manager
}

// NewOSFileTool creates a new OS file tool for full OS file operations.
func NewOSFileTool(manager *host.Manager) *OSFileTool {
	return &OSFileTool{manager: manager}
}

func (t *OSFileTool) Definition() ToolDefinition {
	return ToolDefinition{
		Name:        "os_file",
		Description: "在完整OS环境中读写文件。支持在整个文件系统中自由操作：读取/写入/列出文件，无目录限制。适用于批量文件处理、日志分析、配置文件管理等复杂文件操作。日常简单文件操作请使用 host_file。",
		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 *OSFileTool) Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error) {
	action, _ := args["action"].(string)
	path, _ := args["path"].(string)
	if action == "" || path == "" {
		return &ToolResult{
			ToolName: "os_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: "os_file", Success: false, Error: err.Error()}, nil
		}
		data, _ := json.Marshal(map[string]interface{}{
			"path":    path,
			"content": content,
			"size":    len(content),
		})
		return &ToolResult{ToolName: "os_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: "os_file", Success: false, Error: err.Error()}, nil
		}
		data, _ := json.Marshal(map[string]interface{}{
			"path":    path,
			"written": len(content),
			"status":  "ok",
		})
		return &ToolResult{ToolName: "os_file", Success: true, Data: string(data)}, nil

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

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

// OSSystemTool provides OS-level system information.
type OSSystemTool struct {
	manager *host.Manager
}

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

func (t *OSSystemTool) Definition() ToolDefinition {
	return ToolDefinition{
		Name:        "os_system",
		Description: "获取完整OS环境的系统信息，包括操作系统详情、CPU架构、内存使用、磁盘空间等。与 host_system 不同，此工具返回的是WSL/容器内的完整Linux系统信息。",
		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 *OSSystemTool) Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error) {
	info := t.manager.SystemInfo()
	data, _ := json.Marshal(info)
	return &ToolResult{
		ToolName: "os_system",
		Success:  true,
		Data:     string(data),
	}, nil
}
