package testkit

import (
	"context"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/store/agent"
	"github.com/tidbcloud/AgentTeam/internal/store/message"
	"github.com/tidbcloud/AgentTeam/internal/store/message/testdelivery"
)

// CreateAgentForUser is a test fixture helper for web-agent setup.
func (root *Store) CreateAgentForUser(ctx context.Context, userID string, workspaceID string, machineID string, params agent.CreateAgentParams) (agent.AgentView, error) {
	return root.App().CreateAgentForUser(ctx, userID, workspaceID, machineID, params)
}

// ListAgentsForWorkspace is a test fixture helper for web-agent collection setup.
func (root *Store) ListAgentsForWorkspace(ctx context.Context, userID string, workspaceID string) ([]agent.AppAgent, error) {
	return root.App().ListAgentsForWorkspace(ctx, userID, workspaceID)
}

// ListAgentDirectoryForWorkspace is a test fixture helper for web-agent directory setup.
func (root *Store) ListAgentDirectoryForWorkspace(ctx context.Context, userID string, workspaceID string, options agent.AgentDirectoryOptions) (agent.AgentDirectoryPage, error) {
	return root.App().ListAgentDirectoryForWorkspace(ctx, userID, workspaceID, options)
}

// ListAgentsForWorkspaceWithOptions is a test fixture helper for bounded
// web-agent collection setup.
func (root *Store) ListAgentsForWorkspaceWithOptions(ctx context.Context, userID string, workspaceID string, options agent.AppAgentListOptions) ([]agent.AppAgent, error) {
	return root.App().ListAgentsForWorkspaceWithOptions(ctx, userID, workspaceID, options)
}

// AgentForWorkspace is a test fixture helper for web-agent setup.
func (root *Store) AgentForWorkspace(ctx context.Context, userID string, workspaceID string, agentID string) (agent.AppAgent, error) {
	return root.App().AgentForWorkspace(ctx, userID, workspaceID, agentID)
}

// AgentDetailForWorkspace is a test fixture helper for web-agent detail setup.
func (root *Store) AgentDetailForWorkspace(ctx context.Context, userID string, workspaceID string, agentID string) (agent.AppAgent, error) {
	return root.App().AgentDetailForWorkspace(ctx, userID, workspaceID, agentID)
}

// AgentRuntimeFailureForWorkspace is a test fixture helper for web-agent diagnostics setup.
func (root *Store) AgentRuntimeFailureForWorkspace(ctx context.Context, userID string, workspaceID string, agentID string) (*agent.AgentRuntimeFailureSummary, error) {
	return root.App().AgentRuntimeFailureForWorkspace(ctx, userID, workspaceID, agentID)
}

// AgentRuntimeFailuresForWorkspace is a test fixture helper for web-agent diagnostics setup.
func (root *Store) AgentRuntimeFailuresForWorkspace(ctx context.Context, userID string, workspaceID string, agentIDs []string) (map[string]agent.AgentRuntimeFailureSummary, error) {
	return root.App().AgentRuntimeFailuresForWorkspace(ctx, userID, workspaceID, agentIDs)
}

// GetAgentForUser is a test fixture helper for web-agent setup.
func (root *Store) GetAgentForUser(ctx context.Context, userID string, workspaceID string, agentID string) (agent.AgentView, error) {
	return root.App().GetAgentForUser(ctx, userID, workspaceID, agentID)
}

// UpdateAgentForUser is a test fixture helper for web-agent setup.
func (root *Store) UpdateAgentForUser(ctx context.Context, userID string, workspaceID string, agentID string, params agent.UpdateAgentParams) (agent.AgentView, error) {
	return root.App().UpdateAgentForUser(ctx, userID, workspaceID, agentID, params)
}

// RestoreAgentPermissionModeForUser is a test fixture helper for web-agent setup.
func (root *Store) RestoreAgentPermissionModeForUser(ctx context.Context, userID string, workspaceID string, agentID string, permissionMode string, expectedPermissionMode string) error {
	return root.App().RestoreAgentPermissionModeForUser(ctx, userID, workspaceID, agentID, permissionMode, expectedPermissionMode)
}

// DeleteAgentForWorkspace is a test fixture helper for web-agent setup.
func (root *Store) DeleteAgentForWorkspace(ctx context.Context, userID string, workspaceID string, agentID string) (string, error) {
	return root.App().DeleteAgentForWorkspace(ctx, userID, workspaceID, agentID)
}

// SetAgentAutoWakeForUser is a test fixture helper for web-agent setup.
func (root *Store) SetAgentAutoWakeForUser(ctx context.Context, userID string, workspaceID string, agentID string, autoWake bool) (agent.AgentView, error) {
	return root.App().SetAgentAutoWakeForUser(ctx, userID, workspaceID, agentID, autoWake)
}

// GetAgentWorkspaceReaderForUser is a test fixture helper for web-agent setup.
func (root *Store) GetAgentWorkspaceReaderForUser(ctx context.Context, userID string, workspaceID string, agentID string) (agent.AgentView, error) {
	return root.App().GetAgentWorkspaceReaderForUser(ctx, userID, workspaceID, agentID)
}

// ClearAgentSessionForWorkspace is a test fixture helper for web-agent setup.
func (root *Store) ClearAgentSessionForWorkspace(ctx context.Context, userID string, workspaceID string, agentID string) error {
	return root.App().ClearAgentSessionForWorkspace(ctx, userID, workspaceID, agentID)
}

// AuthenticateAgent is a daemon fixture helper backed by the owning agent store.
func (root *Store) AuthenticateAgent(ctx context.Context, agentID string, bearerToken string) (agent.AuthenticatedAgent, error) {
	return root.Agent().AuthenticateAgent(ctx, agentID, bearerToken)
}

// AgentManagedByUser is a daemon fixture helper backed by the app store.
func (root *Store) AgentManagedByUser(ctx context.Context, workspaceID string, agentID string) (string, error) {
	return root.App().AgentManagedByUser(ctx, workspaceID, agentID)
}

// GetAgentWorkspaceSnapshot is a daemon fixture helper backed by the app store.
func (root *Store) GetAgentWorkspaceSnapshot(ctx context.Context, authenticated agent.AuthenticatedAgent) (agent.WorkspaceSnapshot, error) {
	return root.App().GetAgentWorkspaceSnapshot(ctx, authenticated)
}

// AgentHasUnreadMessages is a fixture helper that checks unconsumed persisted fanout payloads.
func (root *Store) AgentHasUnreadMessages(ctx context.Context, authenticated agent.AuthenticatedAgent) (bool, error) {
	return testdelivery.AgentHasUnreadFanoutMessages(ctx, root.DB, authenticated)
}

// PrepareAgentStart is a daemon fixture helper backed by the owning agent and
// message stores. It exists for integration tests that need a freshly minted
// agent auth token; production startup wiring uses the agent-runtime service.
func (root *Store) PrepareAgentStart(ctx context.Context, agentID string, publicBaseURL string, wakeMessage *message.ReceiveMessage, allowWorkspaceWrite bool, includeLegacySession bool, _ bool) (agent.StartCommand, error) {
	prepared, err := root.Agent().PrepareAgentStart(ctx, agentID, allowWorkspaceWrite, includeLegacySession)
	if err != nil {
		return agent.StartCommand{}, err
	}

	agentName := strings.TrimSpace(prepared.AgentID)
	if root != nil && root.DB != nil {
		var loadedName string
		if err := root.DB.QueryRow(ctx, `
SELECT name
FROM agents
WHERE id = $1 AND workspace_id = $2 AND member_id = $3
`, prepared.AgentID, prepared.WorkspaceID, prepared.MemberID).Scan(&loadedName); err != nil {
			return agent.StartCommand{}, fmt.Errorf("load agent public name: %w", err)
		}
		if strings.TrimSpace(loadedName) != "" {
			agentName = strings.TrimSpace(loadedName)
		}
	}

	unreadThreads, err := root.Message().ListAgentUnreadMessageThreads(ctx, prepared.WorkspaceID, prepared.MemberID)
	if err != nil {
		return agent.StartCommand{}, fmt.Errorf("load agent unread summary: %w", err)
	}
	materialization, err := root.Agent().LoadAgentWorkspaceMaterialization(ctx, prepared.AgentID)
	if err != nil {
		return agent.StartCommand{}, fmt.Errorf("load agent materialization: %w", err)
	}

	return agent.StartCommand{
		AgentID: prepared.AgentID,
		Config: agent.StartConfig{
			Name:                        agentName,
			DisplayName:                 prepared.DisplayName,
			Description:                 prepared.Description,
			Runtime:                     prepared.Runtime,
			PermissionMode:              prepared.PermissionMode,
			RuntimePolicy:               agent.NewRuntimePolicySnapshot(prepared.Runtime, prepared.PermissionMode, prepared.RuntimePolicy.Generation, prepared.VisibleReplyContractEnabled),
			VisibleReplyContractEnabled: prepared.VisibleReplyContractEnabled,
			RuntimeDebugEnabled:         prepared.RuntimeDebugEnabled,
			Model:                       prepared.Model,
			ReasoningEffort:             prepared.ReasoningEffort,
			ServerURL:                   publicBaseURL,
			AuthToken:                   prepared.AuthToken,
			SessionID:                   prepared.SessionID,
			Materialization:             materialization,
		},
		WakeMessage:   wakeMessage,
		UnreadSummary: message.BuildAgentUnreadSummary(unreadThreads),
	}, nil
}
