package app

import (
	"context"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/core/runeffect"
	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/message"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
	"github.com/tidbcloud/AgentTeam/internal/store/serviceactor"
)

// appendAppRuntimeTaskReplyEffect appends the Task-scoped message portion of
// one external App runtime reply. Keeping this producer-specific orchestration
// outside appendAppRuntimeReplyEffect keeps the shared effect settlement
// boundary readable and below the production function-size guardrail.
func appendAppRuntimeTaskReplyEffect(
	ctx context.Context,
	store *Store,
	tx coredb.Tx,
	installation model.RuntimeAppInstallation,
	auth AppRuntimeDeliveryAuth,
	binding serviceEventDeliveryTargetBinding,
	content string,
	params AppRuntimeReplyParams,
	payloadDigest string,
	now time.Time,
) (runeffect.Effect, string, postCommitMessage, *serviceactor.DeliveryEffect, error) {
	appMessage, taskDelivery, err := appendServiceEventTaskDiscussionTx(
		ctx,
		store,
		tx,
		auth.Delivery.WorkspaceID,
		binding,
		content,
		serviceEventTaskDiscussionAppendOptions{
			AuthorMemberID:    strings.TrimSpace(installation.MemberID),
			AuthorTargetID:    strings.TrimSpace(installation.Handle),
			AuthorDisplayName: strings.TrimSpace(installation.AppName),
			AuthorServiceSlug: strings.TrimSpace(installation.AppSlug),
			ClientMessageID:   appRuntimeReplyClientMessageID(auth.Delivery.ID, params.IdempotencyKey),
			Source:            appRuntimeDeliveryContributionSource(auth.Delivery),
			Metadata:          message.CopyMessageMetadata(params.Metadata),
		},
		now,
	)
	if err != nil {
		return runeffect.Effect{}, "", postCommitMessage{}, nil, err
	}
	taskDelivery.AppMessage = &appMessage
	messageID := taskDelivery.MessageID
	if taskDelivery.IdempotentReplay {
		existing, found, idemErr := store.findAppRuntimeReplyEffectByIdempotency(
			ctx, tx, auth.Delivery, auth.Attempt.ID, params.IdempotencyKey, payloadDigest,
		)
		if idemErr != nil {
			return runeffect.Effect{}, "", postCommitMessage{}, nil, idemErr
		}
		if !found || strings.TrimSpace(existing.MessageID) != strings.TrimSpace(messageID) {
			return runeffect.Effect{}, "", postCommitMessage{}, nil, conflict(
				"App reply message replay is missing its canonical effect receipt",
			)
		}
		return runeffect.Effect{}, messageID, postCommitMessage{}, &existing, nil
	}
	prepared, committed, err := store.preparePostCommitMessage(
		ctx,
		tx,
		auth.Delivery.WorkspaceID,
		committedMessageProducerExternalAppRuntimeReply,
		taskDelivery,
	)
	if err != nil {
		return runeffect.Effect{}, "", postCommitMessage{}, nil, err
	}
	return runeffect.MessageEffect(prepared.MessageID), prepared.MessageID, committed, nil, nil
}
