package workbench

import (
	"net/http"
	"strconv"

	"aigateway.local/core/internal/identity"
	"aigateway.local/core/internal/platform/apiresponse"
)

// MarketplaceAdminHTTPHandler exposes the resource-marketplace administration
// surface: shared categories, MCP servers (with connectivity test), skills,
// digital employees, and the unified catalog.
type MarketplaceAdminHTTPHandler struct {
	market     *MarketplaceService
	mcpServers *MCPServerService
	skills     *SkillService
	employees  *DigitalEmployeeService
	mcpClient  *MCPClient
	identity   *identity.Service
	mux        *http.ServeMux
}

func NewMarketplaceAdminHTTPHandler(market *MarketplaceService, mcpServers *MCPServerService, skills *SkillService, employees *DigitalEmployeeService, mcpClient *MCPClient, identityService *identity.Service) *MarketplaceAdminHTTPHandler {
	h := &MarketplaceAdminHTTPHandler{market: market, mcpServers: mcpServers, skills: skills, employees: employees, mcpClient: mcpClient, identity: identityService, mux: http.NewServeMux()}
	h.mux.HandleFunc("GET /api/v1/admin/marketplace-categories", h.listMarketplaceCategories)
	h.mux.HandleFunc("POST /api/v1/admin/marketplace-categories", h.createMarketplaceCategory)
	h.mux.HandleFunc("DELETE /api/v1/admin/marketplace-categories/{id}", h.deleteMarketplaceCategory)
	h.mux.HandleFunc("GET /api/v1/admin/mcp-servers", h.listMCPServers)
	h.mux.HandleFunc("POST /api/v1/admin/mcp-servers", h.createMCPServer)
	h.mux.HandleFunc("GET /api/v1/admin/mcp-servers/{id}", h.getMCPServer)
	h.mux.HandleFunc("PUT /api/v1/admin/mcp-servers/{id}", h.updateMCPServer)
	h.mux.HandleFunc("DELETE /api/v1/admin/mcp-servers/{id}", h.deleteMCPServer)
	h.mux.HandleFunc("POST /api/v1/admin/mcp-servers/{id}/test", h.testMCPServer)
	h.mux.HandleFunc("GET /api/v1/admin/skills", h.listSkills)
	h.mux.HandleFunc("POST /api/v1/admin/skills", h.createSkill)
	h.mux.HandleFunc("GET /api/v1/admin/skills/{id}", h.getSkill)
	h.mux.HandleFunc("PUT /api/v1/admin/skills/{id}", h.updateSkill)
	h.mux.HandleFunc("DELETE /api/v1/admin/skills/{id}", h.deleteSkill)
	h.mux.HandleFunc("POST /api/v1/admin/skills/{id}/render", h.renderSkillPreview)
	h.mux.HandleFunc("GET /api/v1/admin/digital-employees", h.listDigitalEmployees)
	h.mux.HandleFunc("POST /api/v1/admin/digital-employees", h.createDigitalEmployee)
	h.mux.HandleFunc("GET /api/v1/admin/digital-employees/{id}", h.getDigitalEmployee)
	h.mux.HandleFunc("PUT /api/v1/admin/digital-employees/{id}", h.updateDigitalEmployee)
	h.mux.HandleFunc("DELETE /api/v1/admin/digital-employees/{id}", h.deleteDigitalEmployee)
	h.mux.HandleFunc("POST /api/v1/admin/digital-employees/{id}/publish", h.publishDigitalEmployee)
	h.mux.HandleFunc("POST /api/v1/admin/digital-employees/{id}/archive", h.archiveDigitalEmployee)
	h.mux.HandleFunc("GET /api/v1/admin/digital-employees/{id}/runs", h.listDigitalEmployeeRuns)
	h.mux.HandleFunc("GET /api/v1/admin/marketplace/catalog", h.marketplaceCatalog)
	return h
}
func (h *MarketplaceAdminHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	h.mux.ServeHTTP(w, r)
}
func (h *MarketplaceAdminHTTPHandler) require(w http.ResponseWriter, r *http.Request, permission string) (identity.Account, bool) {
	account, err := h.identity.Authenticate(r.Context(), identity.KindAdmin, r.Header.Get("Authorization"))
	if err != nil {
		apiresponse.Error(w, 401, "登录状态无效")
		return account, false
	}
	if !identity.HasPermission(account, permission) {
		apiresponse.Error(w, 403, "缺少资源市场管理权限")
		return account, false
	}
	return account, true
}

// --- 分类 ---

func (h *MarketplaceAdminHTTPHandler) listMarketplaceCategories(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionMarketplaceRead); !ok {
		return
	}
	items, err := h.market.ListCategories(r.Context(), r.URL.Query().Get("type"))
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, items)
}

func (h *MarketplaceAdminHTTPHandler) createMarketplaceCategory(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionMarketplaceManage)
	if !ok {
		return
	}
	var input struct {
		Name         string `json:"name"`
		Description  string `json:"description"`
		ResourceType string `json:"resource_type"`
		SortOrder    int    `json:"sort_order"`
	}
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.market.CreateCategory(r.Context(), Category{Name: input.Name, Description: input.Description, ResourceType: input.ResourceType, SortOrder: input.SortOrder}, a.ID)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) deleteMarketplaceCategory(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionMarketplaceManage)
	if !ok {
		return
	}
	if err := h.market.DeleteCategory(r.Context(), r.PathValue("id"), a.ID); err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, map[string]bool{"deleted": true})
}

// --- MCP 服务器 ---

func (h *MarketplaceAdminHTTPHandler) listMCPServers(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionMCPServerRead); !ok {
		return
	}
	items, err := h.mcpServers.List(r.Context())
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, items)
}

func (h *MarketplaceAdminHTTPHandler) createMCPServer(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionMCPServerManage)
	if !ok {
		return
	}
	var input MCPServerInput
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.mcpServers.Save(r.Context(), "", input, a.ID, true)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) getMCPServer(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionMCPServerRead); !ok {
		return
	}
	item, err := h.mcpServers.Get(r.Context(), r.PathValue("id"))
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) updateMCPServer(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionMCPServerManage)
	if !ok {
		return
	}
	var input MCPServerInput
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.mcpServers.Save(r.Context(), r.PathValue("id"), input, a.ID, false)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) deleteMCPServer(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionMCPServerManage)
	if !ok {
		return
	}
	if err := h.mcpServers.Delete(r.Context(), r.PathValue("id"), a.ID); err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, map[string]bool{"deleted": true})
}

// testMCPServer verifies connectivity and lists the tools an MCP server
// advertises so an operator can confirm it before publishing.
func (h *MarketplaceAdminHTTPHandler) testMCPServer(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionMCPServerManage); !ok {
		return
	}
	server, err := h.mcpServers.Get(r.Context(), r.PathValue("id"))
	if err != nil {
		assetError(w, err)
		return
	}
	headers, err := h.mcpServers.Headers(server)
	if err != nil {
		assetError(w, err)
		return
	}
	tools, err := h.mcpClient.DiscoverTools(r.Context(), server, headers)
	if err != nil {
		apiresponse.Error(w, 502, "MCP 服务器连通性测试失败: "+err.Error())
		return
	}
	apiresponse.OK(w, tools)
}

// --- Skills ---

func (h *MarketplaceAdminHTTPHandler) listSkills(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionSkillRead); !ok {
		return
	}
	items, err := h.skills.List(r.Context())
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, items)
}

func (h *MarketplaceAdminHTTPHandler) createSkill(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionSkillManage)
	if !ok {
		return
	}
	var input SkillInput
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.skills.Save(r.Context(), "", input, a.ID, true)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) getSkill(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionSkillRead); !ok {
		return
	}
	item, err := h.skills.Get(r.Context(), r.PathValue("id"))
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) updateSkill(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionSkillManage)
	if !ok {
		return
	}
	var input SkillInput
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.skills.Save(r.Context(), r.PathValue("id"), input, a.ID, false)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) deleteSkill(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionSkillManage)
	if !ok {
		return
	}
	if err := h.skills.Delete(r.Context(), r.PathValue("id"), a.ID); err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, map[string]bool{"deleted": true})
}

func (h *MarketplaceAdminHTTPHandler) renderSkillPreview(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionSkillRead); !ok {
		return
	}
	var input struct {
		Variables map[string]any `json:"variables"`
	}
	if !decodeAsset(w, r, &input) {
		return
	}
	skill, err := h.skills.Get(r.Context(), r.PathValue("id"))
	if err != nil {
		assetError(w, err)
		return
	}
	rendered, err := h.skills.Render(skill, input.Variables)
	if err != nil {
		apiresponse.Error(w, 400, err.Error())
		return
	}
	apiresponse.OK(w, map[string]any{"code": skill.Code, "name": skill.Name, "rendered": rendered})
}

// --- 数字员工 ---

func (h *MarketplaceAdminHTTPHandler) listDigitalEmployees(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionDigitalEmployeeRead); !ok {
		return
	}
	items, err := h.employees.List(r.Context())
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, items)
}

func (h *MarketplaceAdminHTTPHandler) createDigitalEmployee(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionDigitalEmployeeManage)
	if !ok {
		return
	}
	var input DigitalEmployeeInput
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.employees.Save(r.Context(), "", input, a.ID, true)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) getDigitalEmployee(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionDigitalEmployeeRead); !ok {
		return
	}
	item, err := h.employees.Get(r.Context(), r.PathValue("id"))
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) updateDigitalEmployee(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionDigitalEmployeeManage)
	if !ok {
		return
	}
	var input DigitalEmployeeInput
	if !decodeAsset(w, r, &input) {
		return
	}
	item, err := h.employees.Save(r.Context(), r.PathValue("id"), input, a.ID, false)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) deleteDigitalEmployee(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionDigitalEmployeeManage)
	if !ok {
		return
	}
	if err := h.employees.Delete(r.Context(), r.PathValue("id"), a.ID); err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, map[string]bool{"deleted": true})
}

func (h *MarketplaceAdminHTTPHandler) publishDigitalEmployee(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionDigitalEmployeeManage)
	if !ok {
		return
	}
	item, err := h.employees.Publish(r.Context(), r.PathValue("id"), a.ID)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) archiveDigitalEmployee(w http.ResponseWriter, r *http.Request) {
	a, ok := h.require(w, r, identity.PermissionDigitalEmployeeManage)
	if !ok {
		return
	}
	item, err := h.employees.Archive(r.Context(), r.PathValue("id"), a.ID)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, item)
}

func (h *MarketplaceAdminHTTPHandler) listDigitalEmployeeRuns(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionDigitalEmployeeRead); !ok {
		return
	}
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	items, err := h.employees.ListRuns(r.Context(), r.PathValue("id"), limit)
	if err != nil {
		assetError(w, err)
		return
	}
	apiresponse.OK(w, items)
}

// --- 统一目录 ---

func (h *MarketplaceAdminHTTPHandler) marketplaceCatalog(w http.ResponseWriter, r *http.Request) {
	if _, ok := h.require(w, r, identity.PermissionMarketplaceRead); !ok {
		return
	}
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	query := r.URL.Query()
	items, err := h.market.Catalog(r.Context(), query.Get("type"), query.Get("category_id"), query.Get("tag"), query.Get("q"), limit)
	if err != nil {
		assetError(w, err)
		return
	}
	if items == nil {
		items = []MarketItem{}
	}
	apiresponse.OK(w, items)
}
