package sfcrmappservice

import (
	"context"
	"errors"

	attachmentsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordattachmentsv1"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordviewv1"
)

// RuntimeRecordViewClient is the L1 semantic boundary for the record-view
// capability. The gRPC implementation validates its wire mapping too, but the
// AppService must also validate here: this is the point where an arbitrary
// Runtime port result becomes CRM response data.
//
// Keeping the paired ports behind this adapter makes every transport, test
// double, and future Runtime implementation obey the same closed semantic
// contract before product projection sees a result.
type RuntimeRecordViewClient struct {
	read    RuntimeRecordViewReadFunc
	resolve RuntimeAttachmentSourceProofResolveFunc
}

func NewRuntimeRecordViewClient(read RuntimeRecordViewReadFunc, resolve RuntimeAttachmentSourceProofResolveFunc) (*RuntimeRecordViewClient, error) {
	if read == nil || resolve == nil {
		return nil, errors.New("sfcrm AppService: Runtime record-view read and attachment proof resolver are required")
	}
	return &RuntimeRecordViewClient{read: read, resolve: resolve}, nil
}

func (c *RuntimeRecordViewClient) Read(ctx context.Context, bearer string, request semantic.ReadRequest) (semantic.ReadResponse, error) {
	if err := semantic.ValidateReadRequest(ctx, request); err != nil {
		return semantic.ReadResponse{}, err
	}
	if c == nil || c.read == nil {
		return semantic.ReadResponse{}, &semantic.Failure{Category: semantic.FailureUnavailable}
	}
	response, err := c.read(ctx, bearer, request)
	if err != nil {
		return semantic.ReadResponse{}, err
	}
	if err := semantic.ValidateReadResponse(request, response); err != nil {
		return semantic.ReadResponse{}, err
	}
	return response, nil
}

func (c *RuntimeRecordViewClient) ResolveAttachmentSourceProofs(ctx context.Context, bearer string, request attachmentsemantic.ResolveRequest) (attachmentsemantic.ResolveResponse, error) {
	if err := attachmentsemantic.ValidateRequest(ctx, request); err != nil {
		return attachmentsemantic.ResolveResponse{}, err
	}
	if c == nil || c.resolve == nil {
		return attachmentsemantic.ResolveResponse{}, &attachmentsemantic.Failure{Category: attachmentsemantic.FailureUnavailable}
	}
	response, err := c.resolve(ctx, bearer, request)
	if err != nil {
		return attachmentsemantic.ResolveResponse{}, err
	}
	if err := attachmentsemantic.ValidateResponse(request, response); err != nil {
		return attachmentsemantic.ResolveResponse{}, err
	}
	return response, nil
}
