package com.gzzm.lobster.api.admin;

import com.gzzm.lobster.common.LobsterException;
import com.gzzm.lobster.common.ToolCategory;
import com.gzzm.lobster.common.ToolExecutionMode;
import com.gzzm.lobster.common.ToolRiskLevel;
import com.gzzm.lobster.config.LobsterConfig;
import com.gzzm.lobster.identity.AdminGuard;
import com.gzzm.lobster.tool.ToolDefinitionConfig;
import com.gzzm.lobster.tool.ToolDefinitionConfigDao;
import net.cyan.arachne.HttpMethod;
import net.cyan.arachne.annotation.Service;
import net.cyan.nest.annotation.Inject;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * AdminToolApi —— 工具治理后台 CRUD / Tool governance admin CRUD.
 */
@Service
public class AdminToolApi {

    @Inject private ToolDefinitionConfigDao toolDao;

    @Service(url = "/ai/api/admin/tools/list", method = HttpMethod.all)
    public Map<String, Object> list(Integer offset, Integer limit) throws Exception {
        AdminGuard.requireAdmin();
        int o = offset == null ? 0 : Math.max(0, offset);
        int l = limit == null
                ? LobsterConfig.getListDefaultPageSize()
                : Math.min(LobsterConfig.getListMaxPageSize(), Math.max(1, limit));
        List<ToolDefinitionConfig> rows = toolDao.listAll(o, l);
        List<Map<String, Object>> items = new ArrayList<>();
        for (ToolDefinitionConfig t : rows) items.add(toMap(t));
        Map<String, Object> out = new LinkedHashMap<>();
        out.put("items", items);
        out.put("total", toolDao.countAll());
        out.put("offset", o);
        out.put("limit", l);
        return out;
    }

    @Service(url = "/ai/api/admin/tools/{$0}", method = HttpMethod.all)
    public Map<String, Object> get(String toolName) throws Exception {
        AdminGuard.requireAdmin();
        ToolDefinitionConfig t = toolDao.getByName(toolName);
        if (t == null) throw new LobsterException("admin.tool.not_found", "Tool not found: " + toolName);
        return toMap(t);
    }

    @Service(url = "/ai/api/admin/tools/create", method = HttpMethod.post)
    public Map<String, Object> create(String toolName, String displayName, String description,
                                      String category, String mode, String riskLevel,
                                      Boolean requireConfirm, String mcpServerId,
                                      Boolean enabled) throws Exception {
        AdminGuard.requireAdmin();
        if (toolName == null || toolName.trim().isEmpty()) {
            throw new LobsterException("admin.tool.invalid", "toolName required");
        }
        if (category == null || category.trim().isEmpty()) {
            throw new LobsterException("admin.tool.invalid", "category required");
        }
        if (toolDao.getByName(toolName) != null) {
            throw new LobsterException("admin.tool.conflict", "Tool already exists: " + toolName);
        }
        ToolDefinitionConfig t = new ToolDefinitionConfig();
        t.setToolName(toolName);
        t.setDisplayName(displayName);
        t.setDescription(description);
        t.setCategory(ToolCategory.valueOf(category));
        t.setMode(mode == null ? ToolExecutionMode.SYNC : ToolExecutionMode.valueOf(mode));
        t.setRiskLevel(riskLevel == null ? ToolRiskLevel.READ_ONLY : ToolRiskLevel.valueOf(riskLevel));
        t.setRequireConfirm(Boolean.TRUE.equals(requireConfirm));
        t.setMcpServerId(mcpServerId);
        t.setEnabled(enabled == null ? Boolean.TRUE : enabled);
        t.setOrgId(AdminGuard.requireAdmin().getOrgId());
        t.setCreateTime(new Date());
        t.setUpdateTime(new Date());
        toolDao.save(t);
        return toMap(t);
    }

    @Service(url = "/ai/api/admin/tools/{$0}/update", method = HttpMethod.post)
    public Map<String, Object> update(String toolName, String displayName, String description,
                                      String category, String mode, String riskLevel,
                                      Boolean requireConfirm, String mcpServerId,
                                      Boolean enabled) throws Exception {
        AdminGuard.requireAdmin();
        ToolDefinitionConfig t = toolDao.getByName(toolName);
        if (t == null) throw new LobsterException("admin.tool.not_found", "Tool not found: " + toolName);
        if (displayName != null) t.setDisplayName(displayName);
        if (description != null) t.setDescription(description);
        if (category != null) t.setCategory(ToolCategory.valueOf(category));
        if (mode != null) t.setMode(ToolExecutionMode.valueOf(mode));
        if (riskLevel != null) t.setRiskLevel(ToolRiskLevel.valueOf(riskLevel));
        if (requireConfirm != null) t.setRequireConfirm(requireConfirm);
        if (mcpServerId != null) t.setMcpServerId(mcpServerId);
        if (enabled != null) t.setEnabled(enabled);
        t.setUpdateTime(new Date());
        toolDao.save(t);
        return toMap(t);
    }

    @Service(url = "/ai/api/admin/tools/{$0}/delete", method = HttpMethod.post)
    public Map<String, Object> delete(String toolName) throws Exception {
        AdminGuard.requireAdmin();
        int n = toolDao.deleteByName(toolName);
        Map<String, Object> out = new LinkedHashMap<>();
        out.put("deleted", n);
        return out;
    }

    @Service(url = "/ai/api/admin/tools/{$0}/enabled", method = HttpMethod.post)
    public Map<String, Object> toggleEnabled(String toolName, Boolean enabled) throws Exception {
        AdminGuard.requireAdmin();
        ToolDefinitionConfig t = toolDao.getByName(toolName);
        if (t == null) throw new LobsterException("admin.tool.not_found", "Tool not found: " + toolName);
        t.setEnabled(enabled == null ? !Boolean.TRUE.equals(t.getEnabled()) : enabled);
        t.setUpdateTime(new Date());
        toolDao.save(t);
        return toMap(t);
    }

    private static Map<String, Object> toMap(ToolDefinitionConfig t) {
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("toolName", t.getToolName());
        m.put("displayName", t.getDisplayName());
        m.put("description", t.getDescription());
        m.put("category", t.getCategory());
        m.put("mode", t.getMode());
        m.put("riskLevel", t.getRiskLevel());
        m.put("requireConfirm", t.getRequireConfirm());
        m.put("mcpServerId", t.getMcpServerId());
        m.put("enabled", t.getEnabled());
        m.put("orgId", t.getOrgId());
        m.put("createTime", t.getCreateTime());
        m.put("updateTime", t.getUpdateTime());
        return m;
    }
}
