package mapping

import (
	"context"

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

func ToWireAuthorizeConnectedMailboxRequest(ctx context.Context, request semantic.Request) (*runtimev1.AuthorizeConnectedMailboxRequest, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return nil, err
	}
	if err := semantic.ValidateRequest(ctx, request); err != nil {
		return nil, err
	}
	operation, ok := toWireMailboxOperation(request.Operation)
	if !ok {
		return nil, invalidPlatformWire()
	}
	return &runtimev1.AuthorizeConnectedMailboxRequest{
		Operation:          operation,
		MinCatalogRevision: request.MinCatalogRevision,
	}, nil
}

func FromWireAuthorizeConnectedMailboxRequest(ctx context.Context, request *runtimev1.AuthorizeConnectedMailboxRequest) (semantic.Request, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return semantic.Request{}, err
	}
	if request == nil {
		return semantic.Request{}, invalidPlatformWire()
	}
	operation, ok := fromWireMailboxOperation(request.GetOperation())
	if !ok {
		return semantic.Request{}, invalidPlatformWire()
	}
	result := semantic.Request{
		Operation:          operation,
		MinCatalogRevision: request.MinCatalogRevision,
	}
	if err := semantic.ValidateRequest(ctx, result); err != nil {
		return semantic.Request{}, err
	}
	return result, nil
}

func ToWireAuthorizeConnectedMailboxResponse(request semantic.Request, response semantic.Response) (*runtimev1.AuthorizeConnectedMailboxResponse, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return nil, err
	}
	if err := semantic.ValidateResponse(request, response); err != nil {
		return nil, err
	}
	return &runtimev1.AuthorizeConnectedMailboxResponse{
		AuthorizedSubjectId:   response.AuthorizedSubjectID,
		ReauthorizationHandle: response.ReauthorizationHandle,
		Receipts:              toWireReceipts(response.Receipts, platformCapability(semantic.CapabilityName)),
	}, nil
}

func FromWireAuthorizeConnectedMailboxResponse(request semantic.Request, response *runtimev1.AuthorizeConnectedMailboxResponse) (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))
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), platformCapability(semantic.CapabilityName))
	if err != nil {
		return semantic.Response{}, err
	}
	result := semantic.Response{AuthorizedSubjectID: response.GetAuthorizedSubjectId(), ReauthorizationHandle: response.GetReauthorizationHandle(), Receipts: receipts}
	if err := semantic.ValidateResponse(request, result); err != nil {
		return semantic.Response{}, err
	}
	return result, nil
}

func toWireMailboxOperation(operation semantic.Operation) (runtimev1.ConnectedMailboxOperation, bool) {
	switch operation {
	case semantic.OperationStatus:
		return runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_STATUS, true
	case semantic.OperationBegin:
		return runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_BEGIN, true
	case semantic.OperationDisconnect:
		return runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_DISCONNECT, true
	default:
		return runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_UNSPECIFIED, false
	}
}

func fromWireMailboxOperation(operation runtimev1.ConnectedMailboxOperation) (semantic.Operation, bool) {
	switch operation {
	case runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_STATUS:
		return semantic.OperationStatus, true
	case runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_BEGIN:
		return semantic.OperationBegin, true
	case runtimev1.ConnectedMailboxOperation_CONNECTED_MAILBOX_OPERATION_DISCONNECT:
		return semantic.OperationDisconnect, true
	default:
		return "", false
	}
}

func ToWireReauthorizeConnectedMailboxRequest(ctx context.Context, request semantic.ReauthorizeRequest) (*runtimev1.ReauthorizeConnectedMailboxRequest, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return nil, err
	}
	if err := semantic.ValidateReauthorizeRequest(ctx, request); err != nil {
		return nil, err
	}
	return &runtimev1.ReauthorizeConnectedMailboxRequest{
		ReauthorizationHandle: request.ReauthorizationHandle,
		MinCatalogRevision:    request.MinCatalogRevision,
	}, nil
}

func FromWireReauthorizeConnectedMailboxRequest(ctx context.Context, request *runtimev1.ReauthorizeConnectedMailboxRequest) (semantic.ReauthorizeRequest, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return semantic.ReauthorizeRequest{}, err
	}
	if request == nil {
		return semantic.ReauthorizeRequest{}, invalidPlatformWire()
	}
	result := semantic.ReauthorizeRequest{
		ReauthorizationHandle: request.GetReauthorizationHandle(),
		MinCatalogRevision:    request.MinCatalogRevision,
	}
	if err := semantic.ValidateReauthorizeRequest(ctx, result); err != nil {
		return semantic.ReauthorizeRequest{}, err
	}
	return result, nil
}

func ToWireReauthorizeConnectedMailboxResponse(request semantic.ReauthorizeRequest, response semantic.Response) (*runtimev1.ReauthorizeConnectedMailboxResponse, error) {
	if err := requirePlatformSemanticShape(semantic.CapabilityName); err != nil {
		return nil, err
	}
	if err := semantic.ValidateReauthorizeResponse(request, response); err != nil {
		return nil, err
	}
	return &runtimev1.ReauthorizeConnectedMailboxResponse{
		AuthorizedSubjectId: response.AuthorizedSubjectID,
		Receipts:            toWireReceipts(response.Receipts, platformCapability(semantic.CapabilityName)),
	}, nil
}

func FromWireReauthorizeConnectedMailboxResponse(request semantic.ReauthorizeRequest, response *runtimev1.ReauthorizeConnectedMailboxResponse) (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))
	}
	receipts, err := fromWireReceipts(response.GetReceipts(), platformCapability(semantic.CapabilityName))
	if err != nil {
		return semantic.Response{}, err
	}
	result := semantic.Response{AuthorizedSubjectID: response.GetAuthorizedSubjectId(), Receipts: receipts}
	if err := semantic.ValidateReauthorizeResponse(request, result); err != nil {
		return semantic.Response{}, err
	}
	return result, nil
}
