/*
  This file is part of TALER
  Copyright (C) 2014-2026 Taler Systems SA

  TALER is free software; you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free Software
  Foundation; either version 3, or (at your option) any later version.

  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License along with
  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
/**
 * @file include/taler/exchange/post-batch-deposit.h
 * @brief C interface for POST /batch-deposit
 * @author Christian Grothoff
 */
#ifndef _TALER_EXCHANGE__POST_BATCH_DEPOSIT_H
#define _TALER_EXCHANGE__POST_BATCH_DEPOSIT_H

#include <taler/exchange/common.h>

/**
 * Information needed for a coin to be deposited.
 */
struct TALER_EXCHANGE_CoinDepositDetail
{
  /**
   * The amount to be deposited.
   */
  struct TALER_Amount amount;

  /**
   * Hash over the age commitment of the coin.
   */
  struct TALER_AgeCommitmentHashP h_age_commitment;

  /**
   * The coin's public key.
   */
  struct TALER_CoinSpendPublicKeyP coin_pub;

  /**
   * The signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made
   * by the customer with the coin's private key.
   */
  struct TALER_CoinSpendSignatureP coin_sig;

  /**
   * Exchange's unblinded signature of the coin.
   */
  struct TALER_DenominationSignature denom_sig;

  /**
   * Hash of the public key of the coin.
   */
  struct TALER_DenominationHashP h_denom_pub;
};


/**
 * Meta information about the contract relevant for a coin's deposit
 * operation.
 */
struct TALER_EXCHANGE_DepositContractDetail
{
  /**
   * Hash of the contact of the merchant with the customer (further details
   * are never disclosed to the exchange)
   */
  struct TALER_PrivateContractHashP h_contract_terms;

  /**
   * The public key of the merchant (used to identify the merchant for refund
   * requests).
   */
  struct TALER_MerchantPublicKeyP merchant_pub;

  /**
   * The signature of the merchant (used to show that the merchant indeed
   * agree to the deposit).
   */
  struct TALER_MerchantSignatureP merchant_sig;

  /**
   * Salt used to hash the @e merchant_payto_uri.
   */
  struct TALER_WireSaltP wire_salt;

  /**
   * Hash over data provided by the wallet to customize the contract.
   * All zero if not used.
   */
  struct GNUNET_HashCode wallet_data_hash;

  /**
   * Date until which the merchant can issue a refund to the customer via the
   * exchange (can be zero if refunds are not allowed); must not be after the
   * @e wire_deadline.
   * Note: this should become an option in the future API!
   */
  struct GNUNET_TIME_Timestamp refund_deadline;

  /**
   * Execution date, until which the merchant would like the exchange to
   * settle the balance (advisory, the exchange cannot be forced to settle in
   * the past or upon very short notice, but of course a well-behaved exchange
   * will limit aggregation based on the advice received).
   */
  struct GNUNET_TIME_Timestamp wire_deadline;

  /**
   * Timestamp when the contract was finalized, must match approximately the
   * current time of the exchange.
   */
  struct GNUNET_TIME_Timestamp wallet_timestamp;

  /**
   * The merchant's account details, in the payto://-format supported by the
   * exchange.
   */
  struct TALER_FullPayto merchant_payto_uri;

  /**
   * Metadata to additionally include in the wire transfer subject.
   * Note: this should become an option in the future API!
   */
  const char *extra_wire_subject_metadata;
};


/**
 * Handle for an operation to POST /batch-deposit.
 */
struct TALER_EXCHANGE_PostBatchDepositHandle;


/**
 * Possible options we can set for the POST /batch-deposit request.
 */
enum TALER_EXCHANGE_PostBatchDepositOption
{
  /**
   * End of list of options.
   */
  TALER_EXCHANGE_POST_BATCH_DEPOSIT_OPTION_END = 0,

  /**
   * Change the chance that our deposit confirmation will be given to the
   * auditor to 100%.
   */
  TALER_EXCHANGE_POST_BATCH_DEPOSIT_OPTION_FORCE_DC,

  /**
   * Verify the merchant signature on the contract terms.
   * Not enabled by default as the caller typically just created the signature.
   */
  TALER_EXCHANGE_POST_BATCH_DEPOSIT_OPTION_VERIFY_MERCHANT_SIG

};


/**
 * Value for an option we can set for the POST /batch-deposit request.
 */
struct TALER_EXCHANGE_PostBatchDepositOptionValue
{
  /**
   * Type of the option being set.
   */
  enum TALER_EXCHANGE_PostBatchDepositOption option;

};


/**
 * Set up POST /batch-deposit operation.
 * Note that you must explicitly start the operation after setup.
 *
 * This API is typically used by a merchant.
 *
 * @param ctx curl context
 * @param url exchange base URL
 * @param keys exchange keys
 * @param dcd details about the contract the deposit is for
 * @param num_cdds length of the @a cdds array
 * @param cdds array with details about the coins to be deposited
 * @param[out] ec if NULL is returned, set to the error code explaining why
 *        the operation failed
 * @return handle to operation, NULL if inputs are invalid (in this case
 *         @a ec is set to the error code)
 */
struct TALER_EXCHANGE_PostBatchDepositHandle *
TALER_EXCHANGE_post_batch_deposit_create (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  struct TALER_EXCHANGE_Keys *keys,
  const struct TALER_EXCHANGE_DepositContractDetail *dcd,
  unsigned int num_cdds,
  const struct TALER_EXCHANGE_CoinDepositDetail cdds[static num_cdds],
  enum TALER_ErrorCode *ec);


/**
 * Terminate the list of options.
 *
 * @return the terminating object
 */
#define TALER_EXCHANGE_post_batch_deposit_option_end_()                     \
        (const struct TALER_EXCHANGE_PostBatchDepositOptionValue)           \
        {                                                                   \
          .option = TALER_EXCHANGE_POST_BATCH_DEPOSIT_OPTION_END           \
        }

/**
 * Force the deposit confirmation to be sent to the auditor with 100%
 * probability.
 *
 * @return representation of the option
 */
#define TALER_EXCHANGE_post_batch_deposit_option_force_dc()                 \
        (const struct TALER_EXCHANGE_PostBatchDepositOptionValue)           \
        {                                                                   \
          .option = TALER_EXCHANGE_POST_BATCH_DEPOSIT_OPTION_FORCE_DC      \
        }

/**
 * Enable verification of the merchant signature on the contract terms.
 *
 * @return representation of the option
 */
#define TALER_EXCHANGE_post_batch_deposit_option_verify_merchant_sig()      \
        (const struct TALER_EXCHANGE_PostBatchDepositOptionValue)           \
        {                                                                   \
          .option =                                                         \
            TALER_EXCHANGE_POST_BATCH_DEPOSIT_OPTION_VERIFY_MERCHANT_SIG   \
        }


/**
 * Set the requested options for the operation.
 *
 * If any option fails, other options may or may not be applied.
 *
 * @param pbdh the request to set the options for
 * @param num_options length of the @a options array
 * @param options an array of options
 * @return #GNUNET_OK on success,
 *         #GNUNET_NO on failure,
 *         #GNUNET_SYSERR on internal error
 */
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_post_batch_deposit_set_options_ (
  struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh,
  unsigned int num_options,
  const struct TALER_EXCHANGE_PostBatchDepositOptionValue options[]);


/**
 * Set the requested options for the operation.
 *
 * If any option fails, other options may or may not be applied.
 *
 * @param pbdh the request to set the options for
 * @param ... the list of the options, each created by a
 *            TALER_EXCHANGE_post_batch_deposit_option_NAME(VALUE) macro
 * @return #GNUNET_OK on success,
 *         #GNUNET_NO on failure,
 *         #GNUNET_SYSERR on internal error
 */
#define TALER_EXCHANGE_post_batch_deposit_set_options(pbdh,...)              \
        TALER_EXCHANGE_post_batch_deposit_set_options_ (                     \
          pbdh,                                                              \
          TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE,                     \
          ((const struct TALER_EXCHANGE_PostBatchDepositOptionValue[])      \
           {__VA_ARGS__,                                                    \
            TALER_EXCHANGE_post_batch_deposit_option_end_ ()}               \
          ))


/**
 * Structure with information about a POST /batch-deposit operation's result.
 */
struct TALER_EXCHANGE_PostBatchDepositResponse
{
  /**
   * HTTP response data
   */
  struct TALER_EXCHANGE_HttpResponse hr;

  union
  {
    /**
     * Information returned if the HTTP status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Time when the exchange generated the batch deposit confirmation
       */
      struct GNUNET_TIME_Timestamp deposit_timestamp;

      /**
       * Deposit confirmation signature provided by the exchange
       */
      const struct TALER_ExchangeSignatureP *exchange_sig;

      /**
       * exchange key used to sign @a exchange_sig.
       */
      const struct TALER_ExchangePublicKeyP *exchange_pub;

      /**
       * Base URL for looking up wire transfers, or
       * NULL to use the default base URL.
       */
      const char *transaction_base_url;

      /**
       * Total amount deposited so far under this contract terms for
       * this merchant.
       */
      struct TALER_Amount accumulated_total_without_fee;

    } ok;

    /**
     * Information returned if the HTTP status is #MHD_HTTP_CONFLICT.
     */
    struct
    {
      /**
       * Details depending on the @e hr.ec.
       */
      union
      {
        struct
        {
          /**
           * The coin that had a conflict.
           */
          struct TALER_CoinSpendPublicKeyP coin_pub;

          /**
           * Hash of the denomination public key of the coin.
           */
          struct TALER_DenominationHashP h_denom_pub;
        } insufficient_funds;

        struct
        {
          /**
           * The coin that had a conflict.
           */
          struct TALER_CoinSpendPublicKeyP coin_pub;

          /**
           * Hash of the denomination public key of the coin.
           */
          struct TALER_DenominationHashP h_denom_pub;
        } coin_conflicting_age_hash;

        struct
        {
          /**
           * The coin that had a conflict.
           */
          struct TALER_CoinSpendPublicKeyP coin_pub;
        } coin_conflicting_denomination_key;

      } details;

    } conflict;

    /**
     * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS.
     */
    struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons;

  } details;
};


#ifndef TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE
/**
 * Type of the closure used by
 * the #TALER_EXCHANGE_PostBatchDepositCallback.
 */
#define TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE void
#endif /* TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE */

/**
 * Type of the function that receives the result of a
 * POST /batch-deposit request.
 *
 * @param cls closure
 * @param result result returned by the HTTP server
 */
typedef void
(*TALER_EXCHANGE_PostBatchDepositCallback)(
  TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE *cls,
  const struct TALER_EXCHANGE_PostBatchDepositResponse *result);


/**
 * Start POST /batch-deposit operation.
 *
 * @param[in,out] pbdh operation to start
 * @param cb function to call with the exchange's result
 * @param cb_cls closure for @a cb
 * @return status code, #TALER_EC_NONE on success
 */
enum TALER_ErrorCode
TALER_EXCHANGE_post_batch_deposit_start (
  struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh,
  TALER_EXCHANGE_PostBatchDepositCallback cb,
  TALER_EXCHANGE_POST_BATCH_DEPOSIT_RESULT_CLOSURE *cb_cls);


/**
 * Cancel POST /batch-deposit operation.  This function must not be called by
 * clients after the TALER_EXCHANGE_PostBatchDepositCallback has been invoked
 * (as in those cases it'll be called internally by the implementation
 * already).
 *
 * @param[in] pbdh operation to cancel
 */
void
TALER_EXCHANGE_post_batch_deposit_cancel (
  struct TALER_EXCHANGE_PostBatchDepositHandle *pbdh);


#endif /* _TALER_EXCHANGE__POST_BATCH_DEPOSIT_H */
