syntax = "proto3";

package payments.orchestrator.v1;

option go_package = "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1;orchestratorv1";

import "google/protobuf/timestamp.proto";
import "common/money/v1/money.proto";
import "common/fx/v1/fx.proto";
import "common/gateway/v1/gateway.proto";
import "common/trace/v1/trace.proto";
import "common/pagination/v1/cursor.proto";
import "billing/fees/v1/fees.proto";
import "gateway/chain/v1/chain.proto";
import "gateway/mntx/v1/mntx.proto";
import "oracle/v1/oracle.proto";

enum PaymentKind {
  PAYMENT_KIND_UNSPECIFIED = 0;
  PAYMENT_KIND_PAYOUT = 1;
  PAYMENT_KIND_INTERNAL_TRANSFER = 2;
  PAYMENT_KIND_FX_CONVERSION = 3;
}

// SettlementMode defines how to treat fees/FX variance for payouts.
enum SettlementMode {
  SETTLEMENT_UNSPECIFIED = 0;
  SETTLEMENT_FIX_SOURCE = 1; // customer pays fees; sent amount fixed
  SETTLEMENT_FIX_RECEIVED = 2; // receiver gets fixed amount; source flexes
}

enum PaymentState {
  PAYMENT_STATE_UNSPECIFIED = 0;
  PAYMENT_STATE_ACCEPTED = 1;
  PAYMENT_STATE_FUNDS_RESERVED = 2;
  PAYMENT_STATE_SUBMITTED = 3;
  PAYMENT_STATE_SETTLED = 4;
  PAYMENT_STATE_FAILED = 5;
  PAYMENT_STATE_CANCELLED = 6;
}

enum PaymentFailureCode {
  FAILURE_UNSPECIFIED = 0;
  FAILURE_BALANCE = 1;
  FAILURE_LEDGER = 2;
  FAILURE_FX = 3;
  FAILURE_CHAIN = 4;
  FAILURE_FEES = 5;
  FAILURE_POLICY = 6;
}

message RequestMeta {
  string organization_ref = 1;
  common.trace.v1.TraceContext trace = 2;
}

message LedgerEndpoint {
  string ledger_account_ref = 1;
  string contra_ledger_account_ref = 2;
}

message ManagedWalletEndpoint {
  string managed_wallet_ref = 1;
  chain.gateway.v1.Asset asset = 2;
}

message ExternalChainEndpoint {
  chain.gateway.v1.Asset asset = 1;
  string address = 2;
  string memo = 3;
}

// Card payout destination.
message CardEndpoint {
  oneof card {
    string pan = 1; // raw PAN
    string token = 2; // network or gateway-issued token
  }
  string cardholder_name = 3;
  string cardholder_surname = 4;
  uint32 exp_month = 5;
  uint32 exp_year = 6;
  string country = 7;
  string masked_pan = 8;
}

message PaymentEndpoint {
  oneof endpoint {
    LedgerEndpoint ledger = 1;
    ManagedWalletEndpoint managed_wallet = 2;
    ExternalChainEndpoint external_chain = 3;
    CardEndpoint card = 4;
  }
  map<string, string> metadata = 10;
  string instance_id = 11;
}

message FXIntent {
  common.fx.v1.CurrencyPair pair = 1;
  common.fx.v1.Side side = 2;
  bool firm = 3;
  int64 ttl_ms = 4;
  string preferred_provider = 5;
  int32 max_age_ms = 6;
}

message PaymentIntent {
  PaymentKind kind = 1;
  PaymentEndpoint source = 2;
  PaymentEndpoint destination = 3;
  common.money.v1.Money amount = 4;
  bool requires_fx = 5;
  FXIntent fx = 6;
  fees.v1.PolicyOverrides fee_policy = 7;
  map<string, string> attributes = 8;
  SettlementMode settlement_mode = 9;
  Customer customer = 10;
  string settlement_currency = 11;
  string ref = 12;
}

message Customer {
  string id = 1;
  string first_name = 2;
  string middle_name = 3;
  string last_name = 4;
  string ip = 5;
  string zip = 6;
  string country = 7;
  string state = 8;
  string city = 9;
  string address = 10;
}

message PaymentQuote {
  common.money.v1.Money debit_amount = 1;
  common.money.v1.Money expected_settlement_amount = 2;
  common.money.v1.Money expected_fee_total = 3;
  repeated fees.v1.DerivedPostingLine fee_lines = 4;
  repeated fees.v1.AppliedRule fee_rules = 5;
  oracle.v1.Quote fx_quote = 6;
  chain.gateway.v1.EstimateTransferFeeResponse network_fee = 7;
  string quote_ref = 8;
}

message PaymentQuoteAggregate {
  repeated common.money.v1.Money debit_amounts = 1;
  repeated common.money.v1.Money expected_settlement_amounts = 2;
  repeated common.money.v1.Money expected_fee_totals = 3;
  repeated common.money.v1.Money network_fee_totals = 4;
}

message ExecutionRefs {
  string debit_entry_ref = 1;
  string credit_entry_ref = 2;
  string fx_entry_ref = 3;
  string chain_transfer_ref = 4;
  string card_payout_ref = 5;
  string fee_transfer_ref = 6;
}

message ExecutionStep {
  string code = 1;
  string description = 2;
  common.money.v1.Money amount = 3;
  common.money.v1.Money network_fee = 4;
  string source_wallet_ref = 5;
  string destination_ref = 6;
  string transfer_ref = 7;
  map<string, string> metadata = 8;
  string operation_ref = 9;
}

message ExecutionPlan {
  repeated ExecutionStep steps = 1;
  common.money.v1.Money total_network_fee = 2;
}

message PaymentStep {
  common.gateway.v1.Rail rail = 1;
  string gateway_id = 2; // required for external rails
  common.gateway.v1.RailOperation action = 3;
  common.money.v1.Money amount = 4;
  string step_id = 5;
  string instance_id = 6;
  repeated string depends_on = 7;
  string commit_policy = 8;
  repeated string commit_after = 9;
}

message PaymentPlan {
  string id = 1;
  repeated PaymentStep steps = 2;
  string idempotency_key = 3;
  google.protobuf.Timestamp created_at = 4;
  oracle.v1.Quote fx_quote = 5;
  repeated fees.v1.DerivedPostingLine fees = 6;
}

// Card payout gateway tracking info.
message CardPayout {
  string payout_ref = 1;
  string provider_payment_id = 2;
  string status = 3;
  string failure_reason = 4;
  string card_country = 5;
  string masked_pan = 6;
  string provider_code = 7;
  string gateway_reference = 8;
}

message Payment {
  string payment_ref = 1;
  string idempotency_key = 2;
  PaymentIntent intent = 3;
  PaymentState state = 4;
  PaymentFailureCode failure_code = 5;
  string failure_reason = 6;
  PaymentQuote last_quote = 7;
  ExecutionRefs execution = 8;
  map<string, string> metadata = 9;
  google.protobuf.Timestamp created_at = 10;
  google.protobuf.Timestamp updated_at = 11;
  CardPayout card_payout = 12;
  ExecutionPlan execution_plan = 13;
  PaymentPlan payment_plan = 14;
}

message QuotePaymentRequest {
  RequestMeta meta = 1;
  string idempotency_key = 2;
  PaymentIntent intent = 3;
  bool preview_only = 4;
}

message QuotePaymentResponse {
  PaymentQuote quote = 1;
  string idempotency_key = 2;
}

message QuotePaymentsRequest {
  RequestMeta meta = 1;
  string idempotency_key = 2;
  repeated PaymentIntent intents = 3;
  bool preview_only = 4;
}

message QuotePaymentsResponse {
  string quote_ref = 1;
  PaymentQuoteAggregate aggregate = 2;
  repeated PaymentQuote quotes = 3;
  string idempotency_key = 4;  
}

message InitiatePaymentsRequest {
  RequestMeta meta = 1;
  string idempotency_key = 2;
  string quote_ref = 3;
  map<string, string> metadata = 4;
}

message InitiatePaymentsResponse {
  repeated Payment payments = 1;
}

message InitiatePaymentRequest {
  RequestMeta meta = 1;
  string idempotency_key = 2;
  PaymentIntent intent = 3;
  map<string, string> metadata = 4;
  string quote_ref = 5;
}

message InitiatePaymentResponse {
  Payment payment = 1;
}

message GetPaymentRequest {
  RequestMeta meta = 1;
  string payment_ref = 2;
}

message GetPaymentResponse {
  Payment payment = 1;
}

message ListPaymentsRequest {
  RequestMeta meta = 1;
  repeated PaymentState filter_states = 2;
  string source_ref = 3;
  string destination_ref = 4;
  common.pagination.v1.CursorPageRequest page = 5;
  string organization_ref = 6;
}

message ListPaymentsResponse {
  repeated Payment payments = 1;
  common.pagination.v1.CursorPageResponse page = 2;
}

message CancelPaymentRequest {
  RequestMeta meta = 1;
  string payment_ref = 2;
  string reason = 3;
}

message CancelPaymentResponse {
  Payment payment = 1;
}

message ProcessTransferUpdateRequest {
  RequestMeta meta = 1;
  chain.gateway.v1.TransferStatusChangedEvent event = 2;
}

message ProcessTransferUpdateResponse {
  Payment payment = 1;
}

message ProcessDepositObservedRequest {
  RequestMeta meta = 1;
  chain.gateway.v1.WalletDepositObservedEvent event = 2;
}

message ProcessDepositObservedResponse {
  Payment payment = 1;
}

message ProcessCardPayoutUpdateRequest {
  RequestMeta meta = 1;
  mntx.gateway.v1.CardPayoutStatusChangedEvent event = 2;
}

message ProcessCardPayoutUpdateResponse {
  Payment payment = 1;
}

message InitiateConversionRequest {
  RequestMeta meta = 1;
  string idempotency_key = 2;
  PaymentEndpoint source = 3;
  PaymentEndpoint destination = 4;
  FXIntent fx = 5;
  fees.v1.PolicyOverrides fee_policy = 6;
  map<string, string> metadata = 7;
}

message InitiateConversionResponse {
  Payment conversion = 1;
}

service PaymentOrchestrator {
  rpc QuotePayment(QuotePaymentRequest) returns (QuotePaymentResponse);
  rpc QuotePayments(QuotePaymentsRequest) returns (QuotePaymentsResponse);
  rpc InitiatePayments(InitiatePaymentsRequest) returns (InitiatePaymentsResponse);
  rpc InitiatePayment(InitiatePaymentRequest) returns (InitiatePaymentResponse);
  rpc CancelPayment(CancelPaymentRequest) returns (CancelPaymentResponse);
  rpc GetPayment(GetPaymentRequest) returns (GetPaymentResponse);
  rpc ListPayments(ListPaymentsRequest) returns (ListPaymentsResponse);
  rpc InitiateConversion(InitiateConversionRequest) returns (InitiateConversionResponse);
  rpc ProcessTransferUpdate(ProcessTransferUpdateRequest) returns (ProcessTransferUpdateResponse);
  rpc ProcessDepositObserved(ProcessDepositObservedRequest) returns (ProcessDepositObservedResponse);
  rpc ProcessCardPayoutUpdate(ProcessCardPayoutUpdateRequest) returns (ProcessCardPayoutUpdateResponse);
}
