// Package plan owns browser-facing authoring routes for Workflow Plans.
package plan

import (
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/api/dto/converter"
	planlang "github.com/tidbcloud/AgentTeam/internal/workflow/plan"
	"github.com/tidbcloud/AgentTeam/internal/workflow/planmanage"
)

func planResponse(value planmanage.Plan) dto.WorkflowPlanResponse {
	response := dto.WorkflowPlanResponse{
		ID:            value.ID,
		ScopeID:       value.ScopeID,
		Key:           value.Key,
		DisplayName:   value.DisplayName,
		DescriptionMD: value.DescriptionMD,
		State:         string(value.State),
		Revision:      value.Revision,
		CreatedBy:     actorResponse(value.CreatedBy),
		CreatedAt:     value.CreatedAt,
		UpdatedBy:     actorResponse(value.UpdatedBy),
		UpdatedAt:     value.UpdatedAt,
		ArchivedAt:    value.ArchivedAt,
	}
	if value.CurrentVersion != nil {
		response.CurrentVersion = &dto.WorkflowPlanVersionRefResponse{ID: value.CurrentVersion.ID}
	}
	if value.DefaultVersion != nil {
		response.DefaultVersion = &dto.WorkflowPlanVersionRefResponse{ID: value.DefaultVersion.ID}
	}
	if value.ArchivedBy != nil {
		archivedBy := actorResponse(*value.ArchivedBy)
		response.ArchivedBy = &archivedBy
	}
	return response
}

func editablePlanResponse(value planmanage.Plan) dto.WorkflowPlanResponse {
	response := planResponse(value)
	canEdit := true
	response.CanEdit = &canEdit
	return response
}

func draftResponse(value planmanage.Draft) dto.WorkflowPlanDraftResponse {
	return dto.WorkflowPlanDraftResponse{
		PlanID:    value.PlanID,
		Source:    value.Source,
		Layout:    value.Layout,
		Revision:  value.Revision,
		UpdatedBy: actorResponse(value.UpdatedBy),
		CreatedAt: value.CreatedAt,
		UpdatedAt: value.UpdatedAt,
	}
}

func versionResponse(value planmanage.Version) dto.WorkflowPlanVersionResponse {
	return dto.WorkflowPlanVersionResponse{
		ID:                     value.ID,
		PlanID:                 value.PlanID,
		DraftRevision:          value.DraftRevision,
		SourceVersionID:        value.SourceVersionID,
		Source:                 value.Source,
		Layout:                 value.Layout,
		Artifact:               value.Artifact,
		CompilerVersion:        value.CompilerVersion,
		Digest:                 value.Digest,
		PublishedBy:            actorResponse(value.PublishedBy),
		PublishedByDisplayName: value.PublishedByDisplayName,
		PublishedAt:            value.PublishedAt,
	}
}

func versionSummaryResponse(value planmanage.VersionSummary) dto.WorkflowPlanVersionSummaryResponse {
	return dto.WorkflowPlanVersionSummaryResponse{
		ID:                     value.ID,
		PlanID:                 value.PlanID,
		DraftRevision:          value.DraftRevision,
		SourceVersionID:        value.SourceVersionID,
		CompilerVersion:        value.CompilerVersion,
		Digest:                 value.Digest,
		PublishedBy:            actorResponse(value.PublishedBy),
		PublishedByDisplayName: value.PublishedByDisplayName,
		PublishedAt:            value.PublishedAt,
	}
}

func validationResponse(value planmanage.Validation) dto.WorkflowPlanValidationResponse {
	diagnostics := make([]dto.WorkflowPlanDiagnosticResponse, 0, len(value.Diagnostics))
	for _, diagnostic := range value.Diagnostics {
		diagnostics = append(diagnostics, diagnosticResponse(diagnostic))
	}
	return dto.WorkflowPlanValidationResponse{
		Diagnostics: diagnostics,
		Artifact:    value.Artifact,
		Digest:      value.Digest,
	}
}

func diagnosticResponse(value planlang.Diagnostic) dto.WorkflowPlanDiagnosticResponse {
	return dto.WorkflowPlanDiagnosticResponse{
		Severity: string(value.Severity),
		Code:     value.Code,
		Path:     value.Path,
		Message:  value.Message,
		Line:     value.Line,
		Column:   value.Column,
		NodeID:   value.NodeID,
		EdgeID:   value.EdgeID,
	}
}

func actorResponse(value planmanage.Actor) dto.WorkflowPlanActorResponse {
	return dto.WorkflowPlanActorResponse{Type: value.Type, ID: value.ID, MemberID: value.MemberID}
}

func agentEditMessagesResponse(page planmanage.MessagePage) dto.WorkflowPlanAgentEditMessagesResponse {
	agents := make([]dto.WorkflowPlanAgentEditAgent, 0, len(page.Agents))
	for _, agent := range page.Agents {
		agents = append(agents, agentEditAgentResponse(agent))
	}
	response := dto.WorkflowPlanAgentEditMessagesResponse{
		Messages: converter.ToAppMessages(page.Messages), Agents: agents,
		HasMore: page.HasMore, NextBeforeSeq: page.NextCursor,
	}
	if page.Wake != nil {
		wake := agentEditWakeResponse(*page.Wake)
		response.Wake = &wake
	}
	return response
}

func agentEditAgentsResponse(page planmanage.AgentPage) dto.WorkflowPlanAgentEditAgentsResponse {
	agents := make([]dto.WorkflowPlanAgentEditAgent, 0, len(page.Agents))
	for _, agent := range page.Agents {
		agents = append(agents, agentEditAgentResponse(agent))
	}
	return dto.WorkflowPlanAgentEditAgentsResponse{Agents: agents, NextCursor: page.NextCursor}
}

func agentEditRequestResponse(result planmanage.RequestResult) dto.WorkflowPlanAgentEditRequestResponse {
	return dto.WorkflowPlanAgentEditRequestResponse{
		Message: converter.ToAppMessage(result.Message),
		Target: dto.WorkflowPlanAgentEditTarget{
			Kind: result.Target.Kind, ID: result.Target.ID, NodeType: result.Target.NodeType,
		},
		ResponderAgent:    agentEditAgentResponse(result.Agent),
		BaseDraftRevision: result.BaseDraftRevision,
		Wake:              agentEditWakeResponse(result.Wake),
	}
}

func agentEditAgentResponse(agent planmanage.AgentCandidate) dto.WorkflowPlanAgentEditAgent {
	label := strings.TrimSpace(agent.DisplayName)
	if label == "" {
		label = strings.TrimSpace(agent.Name)
	}
	return dto.WorkflowPlanAgentEditAgent{
		ID: agent.ID, Kind: "agent", Label: label, Token: agent.Name,
		Detail: agent.Description, AvatarURL: agent.AvatarURL, SearchValues: agent.SearchValues,
	}
}

func agentEditWakeResponse(value planmanage.WakeState) dto.WorkflowPlanAgentEditWake {
	return dto.WorkflowPlanAgentEditWake{
		MessageID: value.MessageID, AgentID: value.AgentID,
		BaseDraftRevision: value.BaseDraftRevision,
		Status:            value.Status, Detail: value.Detail,
		Timestamp: value.Timestamp, Active: value.Active,
	}
}
