import 'package:pshared/models/payment/chain_network.dart';
import 'package:pshared/models/payment/fx/side.dart';
import 'package:pshared/models/payment/insufficient_net_policy.dart';
import 'package:pshared/models/payment/kind.dart';
import 'package:pshared/models/payment/type.dart';
import 'package:pshared/models/payment/settlement_mode.dart';


PaymentKind paymentKindFromValue(String? value) {
  switch (value) {
    case 'payout':
      return PaymentKind.payout;
    case 'internal_transfer':
      return PaymentKind.internalTransfer;
    case 'fx_conversion':
      return PaymentKind.fxConversion;
    case 'unspecified':
      return PaymentKind.unspecified;
    default:
      throw ArgumentError('Unknown PaymentKind value: $value');
  }
}

String paymentKindToValue(PaymentKind kind) {
  switch (kind) {
    case PaymentKind.payout:
      return 'payout';
    case PaymentKind.internalTransfer:
      return 'internal_transfer';
    case PaymentKind.fxConversion:
      return 'fx_conversion';
    case PaymentKind.unspecified:
      return 'unspecified';
  }
}

SettlementMode settlementModeFromValue(String? value) {
  switch (value) {
    case 'fix_source':
      return SettlementMode.fixSource;
    case 'fix_received':
      return SettlementMode.fixReceived;
    case 'unspecified':
      return SettlementMode.unspecified;
    default:
      throw ArgumentError('Unknown SettlementMode value: $value');
  }
}

String settlementModeToValue(SettlementMode mode) {
  switch (mode) {
    case SettlementMode.fixSource:
      return 'fix_source';
    case SettlementMode.fixReceived:
      return 'fix_received';
    case SettlementMode.unspecified:
      return 'unspecified';
  }
}

FxSide fxSideFromValue(String? value) {
  switch (value) {
    case 'buy_base_sell_quote':
      return FxSide.buyBaseSellQuote;
    case 'sell_base_buy_quote':
      return FxSide.sellBaseBuyQuote;
    case 'unspecified':
      return FxSide.unspecified;
    default:
      throw ArgumentError('Unknown FxSide value: $value');
  }
}

String fxSideToValue(FxSide side) {
  switch (side) {
    case FxSide.buyBaseSellQuote:
      return 'buy_base_sell_quote';
    case FxSide.sellBaseBuyQuote:
      return 'sell_base_buy_quote';
    case FxSide.unspecified:
      return 'unspecified';
  }
}

ChainNetwork chainNetworkFromValue(String? value) {
  final raw = value ?? '';
  final normalized = _normalizeChainNetwork(raw);
  switch (normalized) {
    case 'ethereum_mainnet':
      return ChainNetwork.ethereumMainnet;
    case 'arbitrum_one':
      return ChainNetwork.arbitrumOne;
    case 'arbitrum_sepolia':
      return ChainNetwork.arbitrumSepolia;
    case 'tron_mainnet':
      return ChainNetwork.tronMainnet;
    case 'tron_nile':
      return ChainNetwork.tronNile;
    case 'unspecified':
      return ChainNetwork.unspecified;
    default:
      throw ArgumentError('Unknown ChainNetwork value: $raw');
  }
}

String chainNetworkToValue(ChainNetwork chain) {
  switch (chain) {
    case ChainNetwork.ethereumMainnet:
      return 'ethereum_mainnet';
    case ChainNetwork.arbitrumOne:
      return 'arbitrum_one';
    case ChainNetwork.tronMainnet:
      return 'tron_mainnet';
    case ChainNetwork.tronNile:
      return 'tron_nile';
    case ChainNetwork.arbitrumSepolia:
      return 'arbitrum_sepolia';
    case ChainNetwork.unspecified:
      return 'unspecified';
  }
}

String _normalizeChainNetwork(String value) {
  final trimmed = value.trim();
  if (trimmed.isEmpty) {
    return 'unspecified';
  }
  final lower = trimmed.toLowerCase();
  const prefix = 'chain_network_';
  if (lower.startsWith(prefix)) {
    return lower.substring(prefix.length);
  }
  return lower;
}

InsufficientNetPolicy insufficientNetPolicyFromValue(String? value) {
  switch (value) {
    case 'block_posting':
      return InsufficientNetPolicy.blockPosting;
    case 'sweep_org_cash':
      return InsufficientNetPolicy.sweepOrgCash;
    case 'invoice_later':
      return InsufficientNetPolicy.invoiceLater;
    case 'unspecified':
      return InsufficientNetPolicy.unspecified;
    default:
      throw ArgumentError('Unknown InsufficientNetPolicy value: $value');
  }
}

String insufficientNetPolicyToValue(InsufficientNetPolicy policy) {
  switch (policy) {
    case InsufficientNetPolicy.blockPosting:
      return 'block_posting';
    case InsufficientNetPolicy.sweepOrgCash:
      return 'sweep_org_cash';
    case InsufficientNetPolicy.invoiceLater:
      return 'invoice_later';
    case InsufficientNetPolicy.unspecified:
      return 'unspecified';
  }
}

PaymentType endpointTypeFromValue(String? value) {
  switch (value) {
    case 'managedWallet':
    case 'managed_wallet':
      return PaymentType.managedWallet;
    case 'cryptoAddress':
    case 'externalChain':
    case 'external_chain':
      return PaymentType.externalChain;
    case 'card':
      return PaymentType.card;
    case 'cardToken':
    case 'card_token':
      return PaymentType.cardToken;
    case 'ledger':
      return PaymentType.ledger;
    case 'bankAccount':
    case 'bank_account':
      return PaymentType.bankAccount;
    case 'iban':
      return PaymentType.iban;
    case 'wallet':
      return PaymentType.wallet;
    default:
      throw ArgumentError('Unknown PaymentType value: $value');
  }
}

String endpointTypeToValue(PaymentType type) {
  switch (type) {
    case PaymentType.ledger:
      return 'ledger';
    case PaymentType.managedWallet:
      return 'managedWallet';
    case PaymentType.externalChain:
      return 'cryptoAddress';
    case PaymentType.card:
      return 'card';
    case PaymentType.cardToken:
      return 'cardToken';
    case PaymentType.bankAccount:
      return 'bankAccount';
    case PaymentType.iban:
      return 'iban';
    case PaymentType.wallet:
      return 'wallet';
  }
}
