package app

import (
	"context"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/core/domain"
	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/access"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
)

func (store *Store) AgentRuntimeFailureForWorkspace(ctx context.Context, userID string, workspaceID string, agentID string) (*agent.AgentRuntimeFailureSummary, error) {
	authorizedAgentIDs, err := store.authorizedRuntimeFailureAgentIDs(ctx, userID, workspaceID, []string{agentID})
	if err != nil {
		return nil, err
	}
	if len(authorizedAgentIDs) == 0 {
		return nil, ErrNotFound
	}
	return store.AgentOps().LoadLatestAgentRuntimeFailureSummary(ctx, workspaceID, authorizedAgentIDs[0])
}

func (store *Store) AgentRuntimeFailuresForWorkspace(ctx context.Context, userID string, workspaceID string, agentIDs []string) (map[string]agent.AgentRuntimeFailureSummary, error) {
	normalizedAgentIDs := normalizeNonEmptyStrings(agentIDs)
	if len(normalizedAgentIDs) == 0 {
		return map[string]agent.AgentRuntimeFailureSummary{}, nil
	}
	if len(normalizedAgentIDs) > agent.MaxAgentRuntimeFailureIDs {
		return nil, badRequest("too many agentIds")
	}
	authorizedAgentIDs, err := store.authorizedRuntimeFailureAgentIDs(ctx, userID, workspaceID, normalizedAgentIDs)
	if err != nil {
		return nil, err
	}
	if len(authorizedAgentIDs) == 0 {
		return map[string]agent.AgentRuntimeFailureSummary{}, nil
	}
	return store.AgentOps().LoadLatestAgentRuntimeFailureSummaries(ctx, workspaceID, authorizedAgentIDs)
}

func (store *Store) authorizedRuntimeFailureAgentIDs(ctx context.Context, userID string, workspaceID string, agentIDs []string) ([]string, error) {
	normalizedAgentIDs := normalizeNonEmptyStrings(agentIDs)
	if len(normalizedAgentIDs) == 0 {
		return []string{}, nil
	}
	workspaceMember, err := store.loadRuntimeWorkspaceMember(ctx, store.db, userID, workspaceID)
	if err != nil {
		return nil, err
	}
	canInspectAll := access.HasWorkspaceAdminRole(domain.WorkspaceRole(workspaceMember.WorkspaceRole))

	requestedAgentsCTE, requestedAgentArgs, _, err := coredb.BuildIndexedStringValuesCTE("requested_agents", "agent_id", "request_order", normalizedAgentIDs, 5)
	if err != nil {
		return nil, err
	}
	args := []any{
		strings.TrimSpace(workspaceID),
		workspaceMember.Member.ID,
		strings.TrimSpace(userID),
		canInspectAll,
	}
	args = append(args, requestedAgentArgs...)
	rows, err := store.db.Query(ctx, `
WITH `+requestedAgentsCTE+`
SELECT a.id
FROM requested_agents requested
JOIN agents a ON a.workspace_id = $1 AND a.id = requested.agent_id
JOIN machines mac ON mac.workspace_id = a.workspace_id AND mac.id = a.machine_id
WHERE a.status <> 'archived'
  AND mac.status = 'active'
  AND (
      $4 OR
      mac.created_by_user_id = $3
  )
ORDER BY requested.request_order ASC
`, args...)
	if err != nil {
		return nil, fmt.Errorf("authorize agent runtime failures: %w", err)
	}
	defer rows.Close()

	authorized := make([]string, 0, len(normalizedAgentIDs))
	for rows.Next() {
		var agentID string
		if err := rows.Scan(&agentID); err != nil {
			return nil, fmt.Errorf("scan authorized runtime failure agent: %w", err)
		}
		authorized = append(authorized, strings.TrimSpace(agentID))
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate authorized runtime failure agents: %w", err)
	}
	return authorized, nil
}
