package mapping

import (
	"context"

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

func ToWireReadApprovalNotificationFlowsRequest(
	ctx context.Context,
	request semantic.Request,
) (*runtimev1.ReadApprovalNotificationFlowsRequest, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return nil, err
	}
	if err := semantic.ValidateRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.ReadApprovalNotificationFlowsRequest{
		MinCatalogRevision: request.MinCatalogRevision,
	}, nil
}

func FromWireReadApprovalNotificationFlowsRequest(
	ctx context.Context,
	request *runtimev1.ReadApprovalNotificationFlowsRequest,
) (semantic.Request, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return semantic.Request{}, err
	}
	if request == nil {
		return semantic.Request{}, invalidPlatformWire()
	}
	mapped := semantic.Request{MinCatalogRevision: request.MinCatalogRevision}
	if err := semantic.ValidateRequest(ctx, mapped); err != nil {
		return semantic.Request{}, err
	}
	return mapped, nil
}

func ToWireReadApprovalNotificationFlowsResponse(
	request semantic.Request,
	response semantic.Response,
) (*runtimev1.ReadApprovalNotificationFlowsResponse, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return nil, err
	}
	if err := semantic.ValidateResponseForRequest(request, response); err != nil {
		return nil, err
	}
	flows := make([]*runtimev1.ApprovalNotificationFlowDescriptor, 0, len(response.Flows))
	for _, flow := range response.Flows {
		flows = append(flows, &runtimev1.ApprovalNotificationFlowDescriptor{
			Name: flow.Name, Label: flow.Label, Description: flow.Description,
		})
	}
	return &runtimev1.ReadApprovalNotificationFlowsResponse{
		Flows: flows,
		Receipts: toWireReceipts(
			response.Receipts,
			platformCapability(semantic.CapabilityName),
		),
	}, nil
}

func FromWireReadApprovalNotificationFlowsResponse(
	request semantic.Request,
	response *runtimev1.ReadApprovalNotificationFlowsResponse,
) (semantic.Response, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return semantic.Response{}, err
	}
	if response == nil || response.GetReceipts() == nil {
		return semantic.Response{}, incompatibleFailureFor(platformCapability(semantic.CapabilityName))
	}
	if len(response.GetFlows()) > semantic.MaxFlows {
		return semantic.Response{}, &semantic.Failure{
			Category:  semantic.FailureResourceExhausted,
			LimitKind: semantic.LimitRecordCount,
			Maximum:   semantic.MaxFlows,
		}
	}
	receipts, err := fromWireReceipts(
		response.GetReceipts(),
		platformCapability(semantic.CapabilityName),
	)
	if err != nil {
		return semantic.Response{}, err
	}
	mapped := semantic.Response{
		Flows:    make([]semantic.FlowDescriptor, 0, len(response.GetFlows())),
		Receipts: receipts,
	}
	for _, flow := range response.GetFlows() {
		if flow == nil {
			return semantic.Response{}, &semantic.Failure{Category: semantic.FailureInternal}
		}
		mapped.Flows = append(mapped.Flows, semantic.FlowDescriptor{
			Name: flow.GetName(), Label: flow.GetLabel(), Description: flow.GetDescription(),
		})
	}
	if err := semantic.ValidateResponseForRequest(request, mapped); err != nil {
		return semantic.Response{}, err
	}
	return mapped, nil
}
