package runtimeapi

import (
	"context"
	"errors"

	"github.com/pingcap-inc/nexuscrm-api-host/runtimegrpc"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/federatedloginv1"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
	"github.com/pingcap-inc/nexuscrm-contract/wire-go/mapping"
)

type FederatedLoginTransactionEngine interface {
	BeginFederatedLogin(context.Context, RuntimeWorkloadCall, semantic.BeginRequest) (semantic.BeginResponse, error)
	ConsumeFederatedLogin(context.Context, RuntimeWorkloadCall, semantic.ConsumeRequest) error
}

// FederatedLoginTransactionServer is the private Runtime projection of the
// existing durable auth owner. It owns neither the transaction state machine
// nor any public/provider-specific request shape.
type FederatedLoginTransactionServer struct {
	runtimev1.UnimplementedFederatedLoginTransactionServiceServer
	engine FederatedLoginTransactionEngine
}

func NewFederatedLoginTransactionServer(engine FederatedLoginTransactionEngine) (*FederatedLoginTransactionServer, error) {
	if engine == nil {
		return nil, errors.New("runtime-api federated login transaction engine is required")
	}
	return &FederatedLoginTransactionServer{engine: engine}, nil
}

func (server *FederatedLoginTransactionServer) BeginFederatedLogin(ctx context.Context, request *runtimev1.BeginFederatedLoginRequest) (*runtimev1.BeginFederatedLoginResponse, error) {
	semanticRequest, err := mapping.FromWireBeginFederatedLoginRequest(ctx, request)
	if err != nil {
		return nil, mapping.ToFederatedLoginRequestStatusError(err)
	}
	authority, ok := RuntimeWorkloadCallFromContext(ctx)
	if !ok {
		return nil, mapping.ToFederatedLoginBeginStatusError(&semantic.Failure{Category: semantic.FailureUnauthenticated})
	}
	response, err := server.engine.BeginFederatedLogin(
		runtimegrpc.WithoutRuntimeSessionCredentials(ctx), authority, semanticRequest,
	)
	if err != nil {
		return nil, mapping.ToFederatedLoginBeginStatusError(err)
	}
	wire, err := mapping.ToWireBeginFederatedLoginResponse(response)
	if err != nil {
		return nil, mapping.ToFederatedLoginBeginStatusError(err)
	}
	return wire, nil
}

func (server *FederatedLoginTransactionServer) ConsumeFederatedLogin(ctx context.Context, request *runtimev1.ConsumeFederatedLoginRequest) (*runtimev1.ConsumeFederatedLoginResponse, error) {
	semanticRequest, err := mapping.FromWireConsumeFederatedLoginRequest(ctx, request)
	if err != nil {
		return nil, mapping.ToFederatedLoginRequestStatusError(err)
	}
	authority, ok := RuntimeWorkloadCallFromContext(ctx)
	if !ok {
		return nil, mapping.ToFederatedLoginConsumeStatusError(&semantic.Failure{Category: semantic.FailureUnauthenticated})
	}
	if err := server.engine.ConsumeFederatedLogin(
		runtimegrpc.WithoutRuntimeSessionCredentials(ctx), authority, semanticRequest,
	); err != nil {
		return nil, mapping.ToFederatedLoginConsumeStatusError(err)
	}
	wire, err := mapping.ToWireConsumeFederatedLoginResponse(semantic.ConsumeResponse{})
	if err != nil {
		return nil, mapping.ToFederatedLoginConsumeStatusError(err)
	}
	return wire, nil
}
