package mapping

import (
	"context"

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

func ToWireRestoreRecycleBinRequest(ctx context.Context, request semantic.Request) (*runtimev1.RestoreRecycleBinRequest, error) {
	if err := semantic.ValidateRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.RestoreRecycleBinRequest{RecordId: request.RecordID, MinCatalogRevision: request.MinCatalogRevision}, nil
}

func FromWireRestoreRecycleBinRequest(ctx context.Context, request *runtimev1.RestoreRecycleBinRequest) (semantic.Request, error) {
	if request == nil {
		return invalidRecycleBinMutationRequest()
	}
	return validateRecycleBinMutationRequest(ctx, request.GetRecordId(), request.MinCatalogRevision)
}

func ToWireRestoreRecycleBinResponse(request semantic.Request, response semantic.Response) (*runtimev1.RestoreRecycleBinResponse, error) {
	if err := semantic.ValidateResponse(request, response); err != nil {
		return nil, err
	}
	return &runtimev1.RestoreRecycleBinResponse{Receipts: toWireReceipts(response.Receipts, recycleBinMutationCapability)}, nil
}

func FromWireRestoreRecycleBinResponse(request semantic.Request, response *runtimev1.RestoreRecycleBinResponse) (semantic.Response, error) {
	if response == nil {
		return semantic.Response{}, incompatibleFailureFor(recycleBinMutationCapability)
	}
	return decodeRecycleBinMutationResponse(request, response.GetReceipts())
}

func ToWirePurgeRecycleBinRequest(ctx context.Context, request semantic.Request) (*runtimev1.PurgeRecycleBinRequest, error) {
	if err := semantic.ValidateRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.PurgeRecycleBinRequest{RecordId: request.RecordID, MinCatalogRevision: request.MinCatalogRevision}, nil
}

func FromWirePurgeRecycleBinRequest(ctx context.Context, request *runtimev1.PurgeRecycleBinRequest) (semantic.Request, error) {
	if request == nil {
		return invalidRecycleBinMutationRequest()
	}
	return validateRecycleBinMutationRequest(ctx, request.GetRecordId(), request.MinCatalogRevision)
}

func ToWirePurgeRecycleBinResponse(request semantic.Request, response semantic.Response) (*runtimev1.PurgeRecycleBinResponse, error) {
	if err := semantic.ValidateResponse(request, response); err != nil {
		return nil, err
	}
	return &runtimev1.PurgeRecycleBinResponse{Receipts: toWireReceipts(response.Receipts, recycleBinMutationCapability)}, nil
}

func FromWirePurgeRecycleBinResponse(request semantic.Request, response *runtimev1.PurgeRecycleBinResponse) (semantic.Response, error) {
	if response == nil {
		return semantic.Response{}, incompatibleFailureFor(recycleBinMutationCapability)
	}
	return decodeRecycleBinMutationResponse(request, response.GetReceipts())
}

func invalidRecycleBinMutationRequest() (semantic.Request, error) {
	return semantic.Request{}, &semantic.Failure{
		Category: semantic.FailureInvalidRequest, InvalidComponent: semantic.InvalidComponentResponse,
	}
}

func validateRecycleBinMutationRequest(ctx context.Context, recordID string, revision *uint64) (semantic.Request, error) {
	result := semantic.Request{RecordID: recordID, MinCatalogRevision: revision}
	if err := semantic.ValidateRequest(ctx, result); err != nil {
		return semantic.Request{}, err
	}
	return result, nil
}

func decodeRecycleBinMutationResponse(request semantic.Request, wireReceipts *commonv1.ConsistencyReceipts) (semantic.Response, error) {
	receipts, err := fromWireReceipts(wireReceipts, recycleBinMutationCapability)
	if err != nil {
		return semantic.Response{}, err
	}
	result := semantic.Response{Receipts: receipts}
	if err := semantic.ValidateResponse(request, result); err != nil {
		return semantic.Response{}, err
	}
	return result, nil
}
