package plan

import (
	"net/http"

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

const workflowAgentEditActiveAtArchiveHeader = "X-AgentTeam-Workflow-Agent-Edit-Active-At-Archive"

func (handler *DetailHandler) Get(r api.WorkspaceScopedRequest) (api.Response, error) {
	id, err := planID(r)
	if err != nil {
		return api.Response{}, err
	}
	plan, err := handler.service.Get(r.Context(), r.WorkspaceID(), id)
	if err != nil {
		return api.Response{}, err
	}
	response := planResponse(plan)
	canEdit, err := handler.planAuthoringAllowed(
		r.Context(), r.WorkspaceID(), id, r.Workspace.MemberID,
	)
	if err != nil {
		return api.Response{}, err
	}
	response.CanEdit = &canEdit
	if handler.planManagementResolver != nil {
		teamID, teamWorkflowID, deleted, linked, err := handler.planManagementResolver.ResolvePlanManagement(
			r.Context(), r.WorkspaceID(), id,
		)
		if err != nil {
			return api.Response{}, err
		}
		if linked {
			relationState := "live"
			if deleted {
				relationState = "deleted"
			}
			response.Management = &dto.WorkflowPlanManagementResponse{
				Kind: "team_workflow", TeamID: teamID,
				TeamWorkflowID: teamWorkflowID, RelationState: relationState,
			}
		}
	}
	return planResponseOK(plan, response), nil
}

func (handler *DetailHandler) Update(r api.WorkspaceScopedJSON[dto.WorkflowPlanUpdateRequest]) (api.Response, error) {
	id, expectedRevision, err := planMutationPreconditions(r.WorkspaceScopedRequest)
	if err != nil {
		return api.Response{}, err
	}
	if err := handler.requireWorkspaceAuthoringAllowed(
		r.Context(), r.WorkspaceID(), id, r.Workspace.MemberID,
	); err != nil {
		return api.Response{}, err
	}
	plan, err := handler.service.UpdateMetadata(r.Context(), planmanage.UpdateMetadataInput{
		WorkspaceID:      r.WorkspaceID(),
		PlanID:           id,
		ExpectedRevision: expectedRevision,
		DisplayName:      r.Body.DisplayName,
		DescriptionMD:    r.Body.DescriptionMD,
		Actor:            requestActor(r.WorkspaceScopedRequest),
	})
	if err != nil {
		return api.Response{}, err
	}
	return planOK(plan), nil
}

func (handler *DetailHandler) Archive(r api.WorkspaceScopedRequest) (api.Response, error) {
	return handler.changeLifecycle(r, true)
}

func (handler *DetailHandler) Restore(r api.WorkspaceScopedRequest) (api.Response, error) {
	return handler.changeLifecycle(r, false)
}

func (handler *DetailHandler) changeLifecycle(r api.WorkspaceScopedRequest, archive bool) (api.Response, error) {
	id, expectedRevision, err := planMutationPreconditions(r)
	if err != nil {
		return api.Response{}, err
	}
	if err := handler.requireDirectPlanMutationAllowed(
		r.Context(), r.WorkspaceID(), id, r.Workspace.MemberID,
	); err != nil {
		return api.Response{}, err
	}
	input := planmanage.LifecycleInput{
		WorkspaceID:      r.WorkspaceID(),
		PlanID:           id,
		ExpectedRevision: expectedRevision,
		Actor:            requestActor(r),
	}
	var plan planmanage.Plan
	if archive {
		plan, err = handler.service.Archive(r.Context(), input)
	} else {
		plan, err = handler.service.Restore(r.Context(), input)
	}
	if err != nil {
		return api.Response{}, err
	}
	response := planOK(plan)
	if archive && handler.agentEdit != nil && plan.ArchivedAt != nil {
		active, activeErr := handler.agentEdit.WasWakeActiveAt(
			r.Context(), r.WorkspaceID(), id, *plan.ArchivedAt,
		)
		if activeErr == nil && active {
			response.Headers.Set(workflowAgentEditActiveAtArchiveHeader, "true")
		}
	}
	return response, nil
}

func planMutationPreconditions(r api.WorkspaceScopedRequest) (string, int64, error) {
	id, err := planID(r)
	if err != nil {
		return "", 0, err
	}
	revision, err := requirePlanRevision(r.Gin.GetHeader("If-Match"), id)
	if err != nil {
		return "", 0, err
	}
	return id, revision, nil
}

func planOK(plan planmanage.Plan) api.Response {
	response := editablePlanResponse(plan)
	return api.Response{
		Status:  http.StatusOK,
		Body:    response,
		Headers: http.Header{"ETag": []string{planETag(plan.ID, plan.Revision)}},
	}
}

func planResponseOK(plan planmanage.Plan, response dto.WorkflowPlanResponse) api.Response {
	return api.Response{
		Status:  http.StatusOK,
		Body:    response,
		Headers: http.Header{"ETag": []string{planETag(plan.ID, plan.Revision)}},
	}
}
