package dialectsfcrm

import (
	"context"
	"encoding/json"
	"errors"
	"reflect"
	"sort"
	"strings"
	"testing"
	"time"

	"github.com/nexuscrm/shared/pkg/contract"
	"github.com/nexuscrm/shared/pkg/models"
	connectordelivery "github.com/pingcap-inc/nexuscrm-connectors/features/connector/delivery"
)

type sendRecordEmailRecordsStub struct {
	record contract.Record
	err    error
	calls  int
	fields []string
}

func (s *sendRecordEmailRecordsStub) ReadTrustedRecordFields(_ context.Context, _, _ string, fields []string, _ *models.UserSession) (contract.Record, error) {
	s.calls++
	s.fields = append([]string(nil), fields...)
	return s.record, s.err
}

type sendRecordEmailPermissionStub struct {
	allowed bool
	calls   int
}

type sendRecordEmailCreatePermissionStub struct {
	allowed      map[string]bool
	deniedFields map[string]bool
	calls        []sendRecordEmailCreatePermissionCall
}

type sendRecordEmailCreatePermissionCall struct {
	objectAPIName string
	fields        []string
}

func (s *sendRecordEmailCreatePermissionStub) CanCreateRecord(_ context.Context, objectAPIName string, fields []string, _ *models.UserSession) bool {
	s.calls = append(s.calls, sendRecordEmailCreatePermissionCall{objectAPIName: objectAPIName, fields: append([]string(nil), fields...)})
	if !s.allowed[objectAPIName] {
		return false
	}
	for _, field := range fields {
		if s.deniedFields[objectAPIName+"."+field] {
			return false
		}
	}
	return true
}

func (s *sendRecordEmailPermissionStub) CanSendRecordEmail(context.Context, *models.UserSession) bool {
	s.calls++
	return s.allowed
}

type sendRecordEmailMailboxStub struct {
	identity ConnectedMailboxIdentity
	err      error
	calls    int
}

func (s *sendRecordEmailMailboxStub) ConnectedMailboxIdentity(context.Context, string, string) (ConnectedMailboxIdentity, error) {
	s.calls++
	return s.identity, s.err
}

type sendRecordEmailDeliveryStub struct {
	lookupResult        connectordelivery.Result
	lookupErr           error
	dispatchResult      connectordelivery.Result
	dispatchErr         error
	completeResult      connectordelivery.Result
	completeErr         error
	lookupCalls         int
	dispatchCalls       int
	completeCalls       int
	request             connectordelivery.Request
	cancelAfterDispatch context.CancelFunc
	completeContextErr  error
}

func (s *sendRecordEmailDeliveryStub) Lookup(context.Context, string, string) (connectordelivery.Result, error) {
	s.lookupCalls++
	return s.lookupResult, s.lookupErr
}

func (s *sendRecordEmailDeliveryStub) Dispatch(_ context.Context, request connectordelivery.Request) (connectordelivery.Result, error) {
	s.dispatchCalls++
	s.request = request
	result := s.dispatchResult
	if len(result.CompletionSnapshot) == 0 {
		result.CompletionSnapshot = append([]byte(nil), request.CompletionSnapshot...)
	}
	if s.cancelAfterDispatch != nil {
		s.cancelAfterDispatch()
	}
	return result, s.dispatchErr
}

func (s *sendRecordEmailDeliveryStub) Complete(ctx context.Context, _, _ string) (connectordelivery.Result, error) {
	s.completeCalls++
	s.completeContextErr = ctx.Err()
	return s.completeResult, s.completeErr
}

type sendRecordEmailWriterStub struct {
	err        error
	calls      int
	records    []ImmutableRecord
	contextErr error
}

func (s *sendRecordEmailWriterStub) EnsureImmutableRecords(ctx context.Context, records []ImmutableRecord, _ *models.UserSession) error {
	s.calls++
	s.contextErr = ctx.Err()
	s.records = records
	return s.err
}

func sendRecordEmailTestDeps() (SendRecordEmailDeps, *sendRecordEmailRecordsStub, *sendRecordEmailPermissionStub, *sendRecordEmailCreatePermissionStub, *sendRecordEmailMailboxStub, *sendRecordEmailDeliveryStub, *sendRecordEmailWriterStub) {
	acceptedAt := time.Date(2026, 7, 19, 1, 2, 3, 456000000, time.UTC)
	records := &sendRecordEmailRecordsStub{record: contract.Record{
		"Id": "003-contact", "Email": "contact@example.com", "HasOptedOutOfEmail": false,
	}}
	permission := &sendRecordEmailPermissionStub{allowed: true}
	createPermission := &sendRecordEmailCreatePermissionStub{allowed: map[string]bool{
		"Task": true, "EmailMessage": true,
	}, deniedFields: map[string]bool{}}
	mailbox := &sendRecordEmailMailboxStub{identity: ConnectedMailboxIdentity{
		ConnectorKey: GmailConnectedMailboxKey, PrincipalAddress: "rep@example.com", Generation: 7,
	}}
	delivery := &sendRecordEmailDeliveryStub{
		lookupErr: connectordelivery.ErrDeliveryNotFound,
		dispatchResult: connectordelivery.Result{
			State: connectordelivery.StateAccepted, AcceptedAt: &acceptedAt,
			RemoteReceiptID: "gmail-message", RemoteConversationID: "gmail-thread", ResponseStatus: 200,
		},
		completeResult: connectordelivery.Result{State: connectordelivery.StateCompleted},
	}
	writer := &sendRecordEmailWriterStub{}
	return SendRecordEmailDeps{
		Records: records, Permission: permission, RecordCreate: createPermission, MailboxIdentity: mailbox,
		Delivery: delivery, RecordWriter: writer,
	}, records, permission, createPermission, mailbox, delivery, writer
}

func TestExecuteSendRecordEmailActionSendsAndWritesL1ActivityMapping(t *testing.T) {
	deps, records, _, createPermission, _, delivery, writer := sendRecordEmailTestDeps()
	result, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact",
		Subject: "Hello", Body: "First line\nSecond line",
	}, &models.UserSession{ID: "005-user"})
	if err != nil {
		t.Fatal(err)
	}
	if result.ProviderMessageID != "gmail-message" || result.ProviderThreadID != "gmail-thread" ||
		result.TaskID == "" || result.EmailMessageID == "" {
		t.Fatalf("result = %+v", result)
	}
	if delivery.lookupCalls != 1 || delivery.dispatchCalls != 1 || delivery.completeCalls != 1 || writer.calls != 1 {
		t.Fatalf("calls lookup/dispatch/complete/write = %d/%d/%d/%d", delivery.lookupCalls, delivery.dispatchCalls, delivery.completeCalls, writer.calls)
	}
	if !reflect.DeepEqual(records.fields, []string{"Id", "Email", "HasOptedOutOfEmail"}) {
		t.Fatalf("recipient fields = %#v", records.fields)
	}
	wantCreatePermissionCalls := []sendRecordEmailCreatePermissionCall{
		{objectAPIName: "Task", fields: SendRecordEmailActivityCreateFields("Task")},
		{objectAPIName: "EmailMessage", fields: SendRecordEmailActivityCreateFields("EmailMessage")},
	}
	if !reflect.DeepEqual(createPermission.calls, wantCreatePermissionCalls) {
		t.Fatalf("create permission checks = %#v", createPermission.calls)
	}
	if delivery.request.ExpectedGeneration != 7 || delivery.request.SourceObject != "Contact" ||
		delivery.request.SourceRecordID != "003-contact" || delivery.request.ConnectorKey != GmailConnectedMailboxKey {
		t.Fatalf("delivery request = %+v", delivery.request)
	}
	raw := string(delivery.request.Payload)
	for _, want := range []string{"From: rep@example.com\r\n", "To: contact@example.com\r\n", "Subject: Hello\r\n", "First line\r\nSecond line"} {
		if !strings.Contains(raw, want) {
			t.Fatalf("raw message missing %q: %q", want, raw)
		}
	}
	wantRecords := []ImmutableRecord{
		{ObjectAPIName: "Task", RecordID: result.TaskID, Fields: contract.Record{
			"WhoId": "003-contact", "Subject": "Email", "ActivityDate": "2026-07-19",
			"Status": "Completed", "Priority": "Normal", "Description": "First line\nSecond line",
			"OwnerId": "005-user", "Type": "Email", "TaskSubtype": "Email",
		}},
		{ObjectAPIName: "EmailMessage", RecordID: result.EmailMessageID, Fields: contract.Record{
			"ActivityId": result.TaskID, "FromAddress": "rep@example.com", "ToAddress": "contact@example.com",
			"Subject": "Hello", "TextBody": "First line\nSecond line", "Incoming": false,
			"Status": "3", "MessageDate": "2026-07-19T01:02:03.456Z",
		}},
	}
	if !reflect.DeepEqual(writer.records, wantRecords) {
		t.Fatalf("activity records = %#v, want %#v", writer.records, wantRecords)
	}
}

func TestExecuteSendRecordEmailActionTreatsNullOptOutAsNotOptedOut(t *testing.T) {
	deps, records, _, _, _, delivery, _ := sendRecordEmailTestDeps()
	records.record[sendRecordEmailRecipientOptOutField] = nil

	if _, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
	}, &models.UserSession{ID: "005-user"}); err != nil {
		t.Fatalf("ExecuteSendRecordEmailAction: %v", err)
	}
	if delivery.dispatchCalls != 1 {
		t.Fatalf("delivery dispatch calls = %d, want 1", delivery.dispatchCalls)
	}
}

func TestExecuteSendRecordEmailActionRejectsMissingOrInvalidOptOutShape(t *testing.T) {
	for _, tt := range []struct {
		name    string
		include bool
		value   any
	}{
		{name: "missing"},
		{name: "invalid string", include: true, value: "false"},
	} {
		t.Run(tt.name, func(t *testing.T) {
			deps, records, _, _, mailbox, delivery, _ := sendRecordEmailTestDeps()
			delete(records.record, sendRecordEmailRecipientOptOutField)
			if tt.include {
				records.record[sendRecordEmailRecipientOptOutField] = tt.value
			}

			_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
				RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
			}, &models.UserSession{ID: "005-user"})
			if err == nil || !strings.Contains(err.Error(), "opt-out state is unavailable") {
				t.Fatalf("error = %v", err)
			}
			if mailbox.calls != 0 || delivery.dispatchCalls != 0 {
				t.Fatalf("calls mailbox/dispatch = %d/%d", mailbox.calls, delivery.dispatchCalls)
			}
		})
	}
}

func TestExecuteSendRecordEmailActionRejectsMissingActivityFieldCreatePermissionBeforeEffect(t *testing.T) {
	for _, objectAPIName := range []string{"Task", "EmailMessage"} {
		for _, field := range SendRecordEmailActivityCreateFields(objectAPIName) {
			t.Run(objectAPIName+"."+field, func(t *testing.T) {
				deps, records, _, createPermission, mailbox, delivery, _ := sendRecordEmailTestDeps()
				createPermission.deniedFields[objectAPIName+"."+field] = true
				_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
					RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
				}, &models.UserSession{ID: "005-user"})
				if err == nil || !strings.Contains(err.Error(), "required field create access") {
					t.Fatalf("error = %v", err)
				}
				if records.calls != 0 || mailbox.calls != 0 || delivery.dispatchCalls != 0 {
					t.Fatalf("calls records/mailbox/dispatch = %d/%d/%d", records.calls, mailbox.calls, delivery.dispatchCalls)
				}
			})
		}
	}
}

func TestExecuteSendRecordEmailActionRejectsSubjectBeyondActivityFieldCapacityBeforeEffect(t *testing.T) {
	for _, test := range []struct {
		name           string
		subject        string
		wantError      bool
		wantDispatches int
	}{
		{name: "ASCII maximum", subject: strings.Repeat("s", SendRecordEmailSubjectMaxLength), wantDispatches: 1},
		{name: "ASCII too long", subject: strings.Repeat("s", SendRecordEmailSubjectMaxLength+1), wantError: true},
		{name: "BMP Unicode maximum", subject: strings.Repeat("界", SendRecordEmailSubjectMaxLength), wantDispatches: 1},
		{name: "BMP Unicode too long", subject: strings.Repeat("界", SendRecordEmailSubjectMaxLength+1), wantError: true},
		{name: "emoji maximum", subject: strings.Repeat("😀", SendRecordEmailSubjectMaxLength), wantDispatches: 1},
		{name: "emoji too long", subject: strings.Repeat("😀", SendRecordEmailSubjectMaxLength+1), wantError: true},
	} {
		t.Run(test.name, func(t *testing.T) {
			deps, _, _, _, _, delivery, _ := sendRecordEmailTestDeps()
			_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
				RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact",
				Subject: test.subject, Body: "Body",
			}, &models.UserSession{ID: "005-user"})
			if (err != nil) != test.wantError {
				t.Fatalf("error = %v, wantError=%t", err, test.wantError)
			}
			if delivery.dispatchCalls != test.wantDispatches {
				t.Fatalf("dispatch calls = %d, want %d", delivery.dispatchCalls, test.wantDispatches)
			}
		})
	}
}

func TestSendRecordEmailActivityCreateFieldsMatchImmutableRecordMapping(t *testing.T) {
	completion := AcceptedEmailCompletion{
		TaskID: "task-1", EmailMessageID: "email-1", UserID: "005-user",
		RecordID: "003-contact", FromAddress: "rep@example.com", ToAddress: "contact@example.com",
		Subject: "Hello", TextBody: "Body",
	}
	for _, record := range acceptedEmailRecords(completion, time.Date(2026, 7, 19, 1, 2, 3, 0, time.UTC)) {
		actual := make([]string, 0, len(record.Fields))
		for field := range record.Fields {
			actual = append(actual, field)
		}
		expected := SendRecordEmailActivityCreateFields(record.ObjectAPIName)
		sort.Strings(actual)
		sort.Strings(expected)
		if !reflect.DeepEqual(actual, expected) {
			t.Fatalf("%s immutable fields = %#v, preflight fields = %#v", record.ObjectAPIName, actual, expected)
		}
	}
}

func TestExecuteSendRecordEmailActionRejectsMissingCreatePermissionBeforeRecipientOrEffect(t *testing.T) {
	deps, records, _, createPermission, mailbox, delivery, _ := sendRecordEmailTestDeps()
	createPermission.allowed["EmailMessage"] = false
	_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
	}, &models.UserSession{ID: "005-user"})
	if err == nil || !strings.Contains(err.Error(), "EmailMessage.Create") {
		t.Fatalf("error = %v", err)
	}
	if records.calls != 0 || mailbox.calls != 0 || delivery.dispatchCalls != 0 {
		t.Fatalf("calls records/mailbox/dispatch = %d/%d/%d", records.calls, mailbox.calls, delivery.dispatchCalls)
	}
}

func TestExecuteSendRecordEmailActionRejectsPermissionBeforeRecipientRead(t *testing.T) {
	deps, records, permission, _, mailbox, delivery, _ := sendRecordEmailTestDeps()
	permission.allowed = false
	_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
	}, &models.UserSession{ID: "005-user"})
	if err == nil || !strings.Contains(err.Error(), SendRecordEmailCustomPermission) {
		t.Fatalf("error = %v", err)
	}
	if records.calls != 0 || mailbox.calls != 0 || delivery.dispatchCalls != 0 {
		t.Fatalf("calls records/mailbox/dispatch = %d/%d/%d", records.calls, mailbox.calls, delivery.dispatchCalls)
	}
}

func TestExecuteSendRecordEmailActionRejectsOptOutBeforeMailboxOrDelivery(t *testing.T) {
	deps, records, _, _, mailbox, delivery, _ := sendRecordEmailTestDeps()
	records.record["HasOptedOutOfEmail"] = true
	_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
	}, &models.UserSession{ID: "005-user"})
	if err == nil || !strings.Contains(err.Error(), "opted out") {
		t.Fatalf("error = %v", err)
	}
	if mailbox.calls != 0 || delivery.dispatchCalls != 0 {
		t.Fatalf("calls mailbox/dispatch = %d/%d", mailbox.calls, delivery.dispatchCalls)
	}
}

func TestExecuteSendRecordEmailActionRecoversAcceptedFromSameFullActionInput(t *testing.T) {
	deps, records, permission, createPermission, mailbox, delivery, writer := sendRecordEmailTestDeps()
	completion := AcceptedEmailCompletion{
		Version: sendRecordEmailCompletionVersion, RequestID: "request-1",
		TaskID:         sendRecordEmailDeterministicID("request-1", "task"),
		EmailMessageID: sendRecordEmailDeterministicID("request-1", "email-message"),
		UserID:         "005-user", ObjectAPIName: "Contact", RecordID: "003-contact",
		FromAddress: "rep@example.com", ToAddress: "original@example.com", Subject: "Original", TextBody: "Original body",
	}
	snapshot, err := json.Marshal(completion)
	if err != nil {
		t.Fatal(err)
	}
	acceptedAt := time.Date(2026, 7, 19, 2, 3, 4, 0, time.UTC)
	delivery.lookupErr = nil
	delivery.lookupResult = connectordelivery.Result{
		State: connectordelivery.StateAccepted, CompletionSnapshot: snapshot, AcceptedAt: &acceptedAt,
		RemoteReceiptID: "gmail-message", RemoteConversationID: "gmail-thread", ResponseStatus: 200,
	}
	permission.allowed = false
	createPermission.allowed["Task"] = false
	createPermission.allowed["EmailMessage"] = false
	records.record["Email"] = "changed@example.com"
	records.record["HasOptedOutOfEmail"] = true
	mailbox.identity.Generation = 8

	result, err := ExecuteSendRecordEmailAction(context.Background(), deps,
		SendRecordEmailInput{
			RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact",
			Subject: "Original", Body: "Original body",
		}, &models.UserSession{ID: "005-user"})
	if err != nil {
		t.Fatal(err)
	}
	if result.ProviderMessageID != "gmail-message" || permission.calls != 0 || len(createPermission.calls) != 0 || records.calls != 0 ||
		mailbox.calls != 0 || delivery.dispatchCalls != 0 || writer.calls != 1 || delivery.completeCalls != 1 {
		t.Fatalf("result=%+v calls permission/create/records/mailbox/dispatch/write/complete=%d/%d/%d/%d/%d/%d/%d",
			result, permission.calls, len(createPermission.calls), records.calls, mailbox.calls,
			delivery.dispatchCalls, writer.calls, delivery.completeCalls)
	}
	if writer.records[1].Fields["ToAddress"] != "original@example.com" {
		t.Fatalf("recovery used mutable recipient: %#v", writer.records)
	}
	if writer.records[0].Fields["Subject"] != sendRecordEmailTaskSubject {
		t.Fatalf("recovery task subject = %#v", writer.records[0].Fields["Subject"])
	}
}

func TestExecuteSendRecordEmailActionRecoversLegacyAcceptedActivityMapping(t *testing.T) {
	deps, _, _, _, _, delivery, writer := sendRecordEmailTestDeps()
	completion := AcceptedEmailCompletion{
		Version: sendRecordEmailLegacyCompletionVersion, RequestID: "request-1",
		TaskID:         sendRecordEmailDeterministicID("request-1", "task"),
		EmailMessageID: sendRecordEmailDeterministicID("request-1", "email-message"),
		UserID:         "005-user", ObjectAPIName: "Contact", RecordID: "003-contact",
		FromAddress: "rep@example.com", ToAddress: "contact@example.com", Subject: "Legacy subject", TextBody: "Body",
	}
	snapshot, err := json.Marshal(completion)
	if err != nil {
		t.Fatal(err)
	}
	acceptedAt := time.Date(2026, 7, 19, 2, 3, 4, 0, time.UTC)
	delivery.lookupErr = nil
	delivery.lookupResult = connectordelivery.Result{
		State: connectordelivery.StateAccepted, CompletionSnapshot: snapshot, AcceptedAt: &acceptedAt,
		RemoteReceiptID: "gmail-message", ResponseStatus: 200,
	}

	_, err = ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact",
		Subject: "Legacy subject", Body: "Body",
	}, &models.UserSession{ID: "005-user"})
	if err != nil {
		t.Fatal(err)
	}
	if delivery.dispatchCalls != 0 || delivery.completeCalls != 1 || writer.calls != 1 {
		t.Fatalf("calls dispatch/write/complete = %d/%d/%d", delivery.dispatchCalls, writer.calls, delivery.completeCalls)
	}
	if writer.records[0].Fields["Subject"] != "Legacy subject" || writer.records[1].Fields["Subject"] != "Legacy subject" {
		t.Fatalf("legacy activity mapping = %#v", writer.records)
	}
}

func TestExecuteSendRecordEmailActionRejectsReplayWithChangedFullInput(t *testing.T) {
	completion := AcceptedEmailCompletion{
		Version: sendRecordEmailCompletionVersion, RequestID: "request-1",
		TaskID:         sendRecordEmailDeterministicID("request-1", "task"),
		EmailMessageID: sendRecordEmailDeterministicID("request-1", "email-message"),
		UserID:         "005-user", ObjectAPIName: "Contact", RecordID: "003-contact",
		FromAddress: "rep@example.com", ToAddress: "contact@example.com", Subject: "Original", TextBody: "Original body",
	}
	snapshot, err := json.Marshal(completion)
	if err != nil {
		t.Fatal(err)
	}
	acceptedAt := time.Date(2026, 7, 19, 2, 3, 4, 0, time.UTC)
	tests := []struct {
		name  string
		input SendRecordEmailInput
	}{
		{name: "request ID", input: SendRecordEmailInput{RequestID: "request-2", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Original", Body: "Original body"}},
		{name: "record ID", input: SendRecordEmailInput{RequestID: "request-1", RecordID: "003-other", ObjectAPIName: "Contact", Subject: "Original", Body: "Original body"}},
		{name: "object", input: SendRecordEmailInput{RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Lead", Subject: "Original", Body: "Original body"}},
		{name: "subject", input: SendRecordEmailInput{RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Changed", Body: "Original body"}},
		{name: "body", input: SendRecordEmailInput{RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Original", Body: "Changed body"}},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			deps, records, permission, createPermission, mailbox, delivery, writer := sendRecordEmailTestDeps()
			delivery.lookupErr = nil
			delivery.lookupResult = connectordelivery.Result{
				State: connectordelivery.StateAccepted, CompletionSnapshot: snapshot, AcceptedAt: &acceptedAt,
				RemoteReceiptID: "gmail-message", ResponseStatus: 200,
			}
			_, err := ExecuteSendRecordEmailAction(context.Background(), deps, test.input, &models.UserSession{ID: "005-user"})
			if err == nil || !strings.Contains(err.Error(), "does not match this action input") {
				t.Fatalf("error = %v", err)
			}
			if permission.calls != 0 || len(createPermission.calls) != 0 || records.calls != 0 || mailbox.calls != 0 ||
				delivery.dispatchCalls != 0 || writer.calls != 0 || delivery.completeCalls != 0 {
				t.Fatalf("changed replay performed work")
			}
		})
	}
}

func TestExecuteSendRecordEmailActionCompletedLookupDoesNotRewriteOrDispatch(t *testing.T) {
	deps, records, permission, createPermission, mailbox, delivery, writer := sendRecordEmailTestDeps()
	completion := AcceptedEmailCompletion{
		Version: sendRecordEmailCompletionVersion, RequestID: "request-1",
		TaskID:         sendRecordEmailDeterministicID("request-1", "task"),
		EmailMessageID: sendRecordEmailDeterministicID("request-1", "email-message"),
		UserID:         "005-user", ObjectAPIName: "Lead", RecordID: "00Q-lead",
		FromAddress: "rep@example.com", ToAddress: "lead@example.com", Subject: "Done", TextBody: "Body",
	}
	snapshot, _ := json.Marshal(completion)
	acceptedAt := time.Date(2026, 7, 19, 2, 3, 4, 0, time.UTC)
	delivery.lookupErr = nil
	delivery.lookupResult = connectordelivery.Result{
		State: connectordelivery.StateCompleted, CompletionSnapshot: snapshot, AcceptedAt: &acceptedAt,
		RemoteReceiptID: "gmail-message", ResponseStatus: 200,
	}
	if _, err := ExecuteSendRecordEmailAction(context.Background(), deps,
		SendRecordEmailInput{
			RequestID: "request-1", RecordID: "00Q-lead", ObjectAPIName: "Lead",
			Subject: "Done", Body: "Body",
		}, &models.UserSession{ID: "005-user"}); err != nil {
		t.Fatal(err)
	}
	if permission.calls != 0 || len(createPermission.calls) != 0 || records.calls != 0 || mailbox.calls != 0 || delivery.dispatchCalls != 0 ||
		writer.calls != 0 || delivery.completeCalls != 0 {
		t.Fatalf("unexpected replay side effects")
	}
}

func TestExecuteSendRecordEmailActionUsesDetachedContextAfterAcceptance(t *testing.T) {
	deps, _, _, _, _, delivery, writer := sendRecordEmailTestDeps()
	ctx, cancel := context.WithCancel(context.Background())
	delivery.cancelAfterDispatch = cancel
	_, err := ExecuteSendRecordEmailAction(ctx, deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
	}, &models.UserSession{ID: "005-user"})
	if err != nil {
		t.Fatal(err)
	}
	if writer.contextErr != nil || delivery.completeContextErr != nil || writer.calls != 1 || delivery.completeCalls != 1 {
		t.Fatalf("post-acceptance contexts writer/complete = %v/%v", writer.contextErr, delivery.completeContextErr)
	}
}

func TestExecuteSendRecordEmailActionLeavesAcceptedDeliveryRetryableWhenActivityWriteFails(t *testing.T) {
	deps, _, _, _, _, delivery, writer := sendRecordEmailTestDeps()
	writer.err = errors.New("database unavailable")
	_, err := ExecuteSendRecordEmailAction(context.Background(), deps, SendRecordEmailInput{
		RequestID: "request-1", RecordID: "003-contact", ObjectAPIName: "Contact", Subject: "Hello", Body: "Body",
	}, &models.UserSession{ID: "005-user"})
	if err == nil || !strings.Contains(err.Error(), "retry with the same request ID") {
		t.Fatalf("error = %v", err)
	}
	if delivery.dispatchCalls != 1 || writer.calls != 1 || delivery.completeCalls != 0 {
		t.Fatalf("calls dispatch/write/complete = %d/%d/%d", delivery.dispatchCalls, writer.calls, delivery.completeCalls)
	}
}

func TestExecuteSendRecordEmailActionNeverTreatsExistingNonAcceptedStateAsNewSend(t *testing.T) {
	deps, _, _, _, _, delivery, writer := sendRecordEmailTestDeps()
	completion := AcceptedEmailCompletion{
		Version: sendRecordEmailCompletionVersion, RequestID: "request-1",
		TaskID:         sendRecordEmailDeterministicID("request-1", "task"),
		EmailMessageID: sendRecordEmailDeterministicID("request-1", "email-message"),
		UserID:         "005-user", ObjectAPIName: "Contact", RecordID: "003-contact",
		FromAddress: "rep@example.com", ToAddress: "contact@example.com", Subject: "Hello", TextBody: "Body",
	}
	snapshot, _ := json.Marshal(completion)
	delivery.lookupErr = nil
	delivery.lookupResult = connectordelivery.Result{State: connectordelivery.StateUncertain, CompletionSnapshot: snapshot}
	_, err := ExecuteSendRecordEmailAction(context.Background(), deps,
		SendRecordEmailInput{RequestID: "request-1"}, &models.UserSession{ID: "005-user"})
	if err == nil || delivery.dispatchCalls != 0 || writer.calls != 0 {
		t.Fatalf("error=%v dispatch/write calls=%d/%d", err, delivery.dispatchCalls, writer.calls)
	}
}
