syntax = "proto3";

package connector.v1;

option go_package = "github.com/tech/sendico/pkg/proto/connector/v1;connectorv1";

import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "common/describable/v1/describable.proto";
import "common/money/v1/money.proto";
import "common/pagination/v1/cursor.proto";

// ConnectorService exposes capability-driven account and operation primitives.
service ConnectorService {
  rpc GetCapabilities(GetCapabilitiesRequest) returns (GetCapabilitiesResponse);

  rpc OpenAccount(OpenAccountRequest) returns (OpenAccountResponse);
  rpc GetAccount(GetAccountRequest) returns (GetAccountResponse);
  rpc ListAccounts(ListAccountsRequest) returns (ListAccountsResponse);
  rpc GetBalance(GetBalanceRequest) returns (GetBalanceResponse);

  rpc SubmitOperation(SubmitOperationRequest) returns (SubmitOperationResponse);
  rpc GetOperation(GetOperationRequest) returns (GetOperationResponse);
  rpc ListOperations(ListOperationsRequest) returns (ListOperationsResponse);
}

enum AccountKind {
  ACCOUNT_KIND_UNSPECIFIED = 0;
  LEDGER_ACCOUNT = 1;
  CHAIN_MANAGED_WALLET = 2;
  EXTERNAL_REF = 3;
}

enum AccountState {
  ACCOUNT_STATE_UNSPECIFIED = 0;
  ACCOUNT_ACTIVE = 1;
  ACCOUNT_SUSPENDED = 2;
  ACCOUNT_CLOSED = 3;
}

enum OperationType {
  OPERATION_TYPE_UNSPECIFIED = 0;
  CREDIT = 1;
  DEBIT = 2;
  TRANSFER = 3;
  PAYOUT = 4;
  FEE_ESTIMATE = 5;
  FX = 6;
  GAS_TOPUP = 7;
}

enum OperationStatus {
  OPERATION_STATUS_UNSPECIFIED = 0;
  SUBMITTED = 1;
  PENDING = 2;
  CONFIRMED = 3;
  FAILED = 4;
  CANCELED = 5;
}

enum ParamType {
  PARAM_TYPE_UNSPECIFIED = 0;
  STRING = 1;
  INT = 2;
  BOOL = 3;
  DECIMAL_STRING = 4;
  JSON = 5;
}

enum ErrorCode {
  ERROR_CODE_UNSPECIFIED = 0;
  UNSUPPORTED_OPERATION = 1;
  UNSUPPORTED_ACCOUNT_KIND = 2;
  INVALID_PARAMS = 3;
  INSUFFICIENT_FUNDS = 4;
  NOT_FOUND = 5;
  TEMPORARY_UNAVAILABLE = 6;
  RATE_LIMITED = 7;
  PROVIDER_ERROR = 8;
}

message ParamSpec {
  string key = 1;
  ParamType type = 2;
  bool required = 3;
  string description = 4;
  repeated string allowed_values = 5;
  google.protobuf.Struct example = 6;
}

message OperationParamSpec {
  OperationType operation_type = 1;
  repeated ParamSpec params = 2;
}

message ConnectorCapabilities {
  string connector_type = 1;
  string version = 2;
  repeated AccountKind supported_account_kinds = 3;
  repeated OperationType supported_operation_types = 4;
  repeated string supported_assets = 5;   // canonical asset string (USD, ETH, USDT-TRC20)
  repeated string supported_networks = 6; // optional, connector-defined names
  repeated ParamSpec open_account_params = 7;
  repeated OperationParamSpec operation_params = 8;
  map<string, string> metadata = 9;
}

message AccountRef {
  string connector_id = 1;
  string account_id = 2;
}

message ExternalRef {
  string external_ref = 1;
  google.protobuf.Struct details = 2;
}

message OperationParty {
  oneof ref {
    AccountRef account = 1;
    ExternalRef external = 2;
  }
}

message Account {
  AccountRef ref = 1;
  AccountKind kind = 2;
  string asset = 3; // canonical asset string (USD, ETH, USDT-TRC20)
  AccountState state = 4;
  string label = 5;
  string owner_ref = 6; // optional account_ref; empty means organization-owned
  google.protobuf.Struct provider_details = 7;
  google.protobuf.Timestamp created_at = 8;
  google.protobuf.Timestamp updated_at = 9;
  common.describable.v1.Describable describable = 10;
}

message Balance {
  AccountRef account_ref = 1;
  common.money.v1.Money available = 2;
  common.money.v1.Money pending_inbound = 3;
  common.money.v1.Money pending_outbound = 4;
  google.protobuf.Timestamp calculated_at = 5;
}

message ConnectorError {
  ErrorCode code = 1;
  string message = 2;
  google.protobuf.Struct details = 3;
  string correlation_id = 4;
  string parent_intent_id = 5;
  string operation_id = 6;
  string account_id = 7;
}

message Operation {
  string operation_id = 1;
  OperationType type = 2;
  OperationParty from = 3;
  OperationParty to = 4;
  common.money.v1.Money money = 5;
  string idempotency_key = 6;
  google.protobuf.Struct params = 7;
  string correlation_id = 8;
  string parent_intent_id = 9;
  OperationStatus status = 10;
  string provider_ref = 11;
  google.protobuf.Timestamp created_at = 12;
  google.protobuf.Timestamp updated_at = 13;
}

message OperationReceipt {
  string operation_id = 1;
  OperationStatus status = 2;
  string provider_ref = 3;
  ConnectorError error = 4;
  google.protobuf.Struct result = 5; // connector-specific output payload
}

message GetCapabilitiesRequest {}

message GetCapabilitiesResponse {
  ConnectorCapabilities capabilities = 1;
}

message OpenAccountRequest {
  string idempotency_key = 1;
  AccountKind kind = 2;
  string asset = 3; // canonical asset string (USD, ETH, USDT-TRC20)
  string label = 4;
  string owner_ref = 5; // optional account_ref; empty means organization-owned
  google.protobuf.Struct params = 6;
  string correlation_id = 7;
  string parent_intent_id = 8;
}

message OpenAccountResponse {
  Account account = 1;
  ConnectorError error = 2;
}

message GetAccountRequest {
  AccountRef account_ref = 1;
}

message GetAccountResponse {
  Account account = 1;
}

message ListAccountsRequest {
  string owner_ref = 1;
  AccountKind kind = 2;
  string asset = 3; // canonical asset string (USD, ETH, USDT-TRC20)
  common.pagination.v1.CursorPageRequest page = 4;
  string organization_ref = 5; // optional org scope (preferred over owner_ref)
}

message ListAccountsResponse {
  repeated Account accounts = 1;
  common.pagination.v1.CursorPageResponse page = 2;
}

message GetBalanceRequest {
  AccountRef account_ref = 1;
}

message GetBalanceResponse {
  Balance balance = 1;
}

message SubmitOperationRequest {
  Operation operation = 1;
}

message SubmitOperationResponse {
  OperationReceipt receipt = 1;
}

message GetOperationRequest {
  string operation_id = 1;
}

message GetOperationResponse {
  Operation operation = 1;
}

message ListOperationsRequest {
  AccountRef account_ref = 1;
  OperationType type = 2;
  OperationStatus status = 3;
  string correlation_id = 4;
  string parent_intent_id = 5;
  common.pagination.v1.CursorPageRequest page = 6;
}

message ListOperationsResponse {
  repeated Operation operations = 1;
  common.pagination.v1.CursorPageResponse page = 2;
}
