package agent

import (
	"context"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/service/agentruntime"
	"github.com/tidbcloud/AgentTeam/internal/service/channeladmin"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
	"github.com/tidbcloud/AgentTeam/internal/store/agentops"
	"github.com/tidbcloud/AgentTeam/internal/store/app"
	"github.com/tidbcloud/AgentTeam/internal/store/channel"
	"github.com/tidbcloud/AgentTeam/internal/store/identity"
	"github.com/tidbcloud/AgentTeam/internal/store/message"
	"github.com/tidbcloud/AgentTeam/internal/store/reaction"
	"github.com/tidbcloud/AgentTeam/internal/store/review"
	"github.com/tidbcloud/AgentTeam/internal/store/rewind"
	"github.com/tidbcloud/AgentTeam/internal/store/team"
)

type StorePortsDeps struct {
	Agents           *agent.Service
	App              *app.Store
	Channel          *channel.Store
	Identity         *identity.Store
	Messages         *message.Store
	Reactions        *reaction.Store
	Rewind           *rewind.Store
	Review           *review.Store
	ApprovalSubjects ApprovalRuntime
	Teams            *team.Store
	SourceContexts   TaskSourceThreadContextStore

	// Agent management dependencies. AgentRuntime is the auto-wake-aware
	// start/stop orchestrator; AgentOps is the direct-lifecycle receipt ledger.
	// Both are optional: when nil the managed-agent routes are not registered.
	AgentRuntime *agentruntime.Service
	AgentOps     *agentops.Store

	// ChannelManagement is the optional Agent Exec channel management service.
	// When nil the Agent channel routes are not registered.
	ChannelManagement *channeladmin.Service
}

type appMessageStore struct {
	*app.Store
	messages *message.Store
}

func (s *appMessageStore) SendAgentMessage(ctx context.Context, sender agent.AuthenticatedAgent, params message.SendMessageParams) (message.MessageDelivery, error) {
	if strings.TrimSpace(params.TaskScopeID) != "" {
		return s.Store.SendAgentTaskScopeMessage(ctx, sender, params)
	}
	return s.Store.SendAgentThreadMessage(ctx, sender, params)
}

func (s *appMessageStore) SendAgentMessageWithFreshness(ctx context.Context, sender agent.AuthenticatedAgent, params message.SendMessageParams) (message.SendMessageResult, error) {
	if strings.TrimSpace(params.TaskScopeID) != "" {
		return s.Store.SendAgentTaskScopeMessageWithFreshness(ctx, sender, params)
	}
	return s.Store.SendAgentThreadMessageWithFreshness(ctx, sender, params)
}

func (s *appMessageStore) ListScopeHistoryForAgent(ctx context.Context, authenticatedAgent agent.AuthenticatedAgent, request message.ScopeAPIHistoryRequest) (message.ScopeAPIHistoryPage, error) {
	request.WorkspaceID = authenticatedAgent.WorkspaceID
	request.ViewerMemberID = authenticatedAgent.MemberID
	request.ViewerType = message.ScopeActorAgent
	request.RequestKind = message.ScopeVisibilityRequestHistory
	request.IncludeReplyThreadRoot = true
	return message.NewScopeAPIService(s.messages).ListHistory(ctx, request)
}

func (s *appMessageStore) SearchScopeMessagesForAgent(ctx context.Context, authenticatedAgent agent.AuthenticatedAgent, request message.ScopeAPISearchRequest) (message.ScopeAPISearchPage, error) {
	request.WorkspaceID = authenticatedAgent.WorkspaceID
	request.ViewerMemberID = authenticatedAgent.MemberID
	request.ViewerType = message.ScopeActorAgent
	return message.NewScopeAPIService(s.messages).SearchMessages(ctx, request)
}

func (s *appMessageStore) CanReadScopeMessageForAgent(ctx context.Context, authenticatedAgent agent.AuthenticatedAgent, request message.ScopeAPIReadCheckRequest) (message.ScopeAPIReadCheckResult, error) {
	request.WorkspaceID = authenticatedAgent.WorkspaceID
	request.ViewerMemberID = authenticatedAgent.MemberID
	request.ViewerType = message.ScopeActorAgent
	return message.NewScopeAPIService(s.messages).CanReadMessage(ctx, request)
}

func (s *appMessageStore) ListScopeMemberDisplayRowsForAgent(ctx context.Context, authenticatedAgent agent.AuthenticatedAgent, request message.ScopeMemberListRequest) (message.ScopeMemberListPage, error) {
	request.WorkspaceID = authenticatedAgent.WorkspaceID
	request.ViewerMemberID = authenticatedAgent.MemberID
	return message.NewScopeAPIService(s.messages).ListMemberDisplayRowsPage(ctx, request)
}

func (s *appMessageStore) ResolveAgentThreadAttestation(ctx context.Context, authenticatedAgent agent.AuthenticatedAgent, target AgentThreadTarget) (AgentThreadAttestation, error) {
	resolved, err := s.Store.ResolveAgentThreadTargetContextForAgent(ctx, authenticatedAgent, target)
	if err != nil {
		return AgentThreadAttestation{}, err
	}
	return resolved, nil
}

func firstNonEmpty(values ...string) string {
	for _, value := range values {
		if trimmed := strings.TrimSpace(value); trimmed != "" {
			return trimmed
		}
	}
	return ""
}
