package webagent

import (
	"log/slog"
	"net/http"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/api/dto/converter"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
)

const (
	agentDuplicateModeConfigOnly   = "config_only"
	agentDuplicateModeWithResource = "with_resources"
	agentDuplicateCleanupTimeout   = 15 * time.Second
)

type DuplicateHandler struct {
	agentStore            AgentStore
	machineAccess         MachineAccessChecker
	orgs                  OrganizationProvider
	hostedAgents          HostedAgentValidator
	resourceCopy          AgentResourceCopier
	knowledgeBasesEnabled bool
	runtime               Runtime
	realtime              Realtime
	logger                *slog.Logger
}

func (handler *DuplicateHandler) Duplicate(r api.WorkspaceScopedJSON[dto.WebAgentDuplicateRequest]) (api.Response, error) {
	sourceAgentID := strings.TrimSpace(r.Gin.Param("agentId"))
	if sourceAgentID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "agentId is required")
	}
	svc := NewAgentService(handler.agentStore, nil, handler.runtime, handler.realtime, handler.logger, handler.machineAccess, handler.orgs, handler.hostedAgents, handler.resourceCopy, handler.knowledgeBasesEnabled, nil, nil)
	createdAgent, resourceCopy, err := svc.DuplicateAgent(r.Context(), r.UserID(), r.WorkspaceID(), sourceAgentID, DuplicateAgentInput{
		Mode:        r.Body.Mode,
		Name:        r.Body.Name,
		DisplayName: r.Body.DisplayName,
		MachineID:   r.Body.MachineID,
		Runtime:     r.Body.Runtime,
		ChannelIDs:  r.Body.ChannelIDs,
		Identity:    NewAgentResourceCopyIdentityForWeb(r.User),
	})
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(dto.WebAgentDuplicateResponse{Agent: converter.ToAppAgent(createdAgent), ResourceCopy: resourceCopy}), nil
}

func duplicateModeCopiesResources(mode string) (bool, error) {
	switch strings.TrimSpace(mode) {
	case "", agentDuplicateModeConfigOnly:
		return false, nil
	case agentDuplicateModeWithResource:
		return true, nil
	default:
		return false, api.NewHTTPError(http.StatusBadRequest, "invalid duplicate mode")
	}
}

func duplicateFallbackDisplayName(source agent.AppAgent) string {
	name := strings.TrimSpace(source.DisplayName)
	if name == "" {
		name = strings.TrimSpace(source.Name)
	}
	if name == "" {
		return ""
	}
	return name + " copy"
}

func agentResourceCopyAgentFromApp(appAgent agent.AppAgent) AgentResourceCopyAgent {
	return AgentResourceCopyAgent{
		ID:          strings.TrimSpace(appAgent.ID),
		Name:        strings.TrimSpace(appAgent.Name),
		DisplayName: strings.TrimSpace(appAgent.DisplayName),
	}
}
