package mapping

import (
	"context"
	"testing"
	"time"

	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/bulkingestv1"
	common "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
)

func TestBulkIngestMappingsRoundTripEveryLifecycleOperation(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	create := semantic.CreateRequest{ObjectID: "Account", Operation: semantic.OperationUpsert, ExternalIDFieldName: "External_Id__c", ClientVersion: 62}
	wireCreate, err := ToWireCreateBulkIngestJobRequest(ctx, create)
	if err != nil {
		t.Fatal(err)
	}
	roundCreate, err := FromWireCreateBulkIngestJobRequest(ctx, wireCreate)
	if err != nil || roundCreate != create {
		t.Fatalf("create round trip = %#v, %v", roundCreate, err)
	}

	job := semantic.Job{ID: "job-1", ObjectID: "Account", Operation: semantic.OperationUpsert, State: semantic.StateOpen, CreatedByID: "user-1", CreatedAt: "2026-08-27T10:00:00Z", ModifiedAt: "2026-08-27T10:00:00Z", ExternalIDFieldName: "External_Id__c", ClientVersion: 62}
	receipts := common.Receipts{ProtocolVersion: "1.0", CapabilityVersion: semantic.CapabilityName}
	readRequest := semantic.ReadRequest{JobID: job.ID}
	wireRead, err := ToWireReadBulkIngestJobResponse(readRequest, semantic.ReadResponse{Job: job, Receipts: receipts})
	if err != nil {
		t.Fatal(err)
	}
	roundRead, err := FromWireReadBulkIngestJobResponse(readRequest, wireRead)
	if err != nil || roundRead.Job != job {
		t.Fatalf("read round trip = %#v, %v", roundRead, err)
	}

	header := semantic.UploadHeader{JobID: job.ID, ContentLength: 3, ContentLengthKnown: true}
	for _, chunk := range []semantic.UploadChunk{{Header: &header}, {Data: []byte("abc")}} {
		wireChunk, mapErr := ToWireUploadBulkIngestChunk(chunk)
		if mapErr != nil {
			t.Fatal(mapErr)
		}
		roundChunk, mapErr := FromWireUploadBulkIngestChunk(wireChunk)
		if mapErr != nil {
			t.Fatal(mapErr)
		}
		if chunk.Header != nil && (roundChunk.Header == nil || *roundChunk.Header != *chunk.Header) {
			t.Fatalf("header round trip = %#v", roundChunk)
		}
		if string(roundChunk.Data) != string(chunk.Data) {
			t.Fatalf("data round trip = %q", roundChunk.Data)
		}
	}
	upload := semantic.UploadResponse{JobID: job.ID, Receipts: receipts}
	wireUpload, err := ToWireUploadBulkIngestResponse(header, upload)
	if err != nil {
		t.Fatal(err)
	}
	roundUpload, err := FromWireUploadBulkIngestResponse(header, wireUpload)
	if err != nil || roundUpload.JobID != job.ID {
		t.Fatalf("upload response round trip = %#v, %v", roundUpload, err)
	}
	wireUpload.JobId = "foreign-job"
	if _, err := FromWireUploadBulkIngestResponse(header, wireUpload); err == nil {
		t.Fatal("foreign upload response was accepted")
	}
	wireRead.Job.FailureCode = runtimev1.BulkIngestFailureCode(99)
	if _, err := FromWireReadBulkIngestJobResponse(readRequest, wireRead); err == nil {
		t.Fatal("unknown wire failure code was accepted")
	}
}
