/*
  This file is part of Anastasis
  Copyright (C) 2020-2022 Anastasis SARL

  Anastasis 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.

  Anastasis 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
  Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
*/
/**
 * @file stasis/iterate_auth_iban_transfers.c
 * @brief Anastasis database: iterate auth iban transfers
 * @author Christian Grothoff
 */
#include "platform.h"
#include "anastasis-db_pg.h"
#include "anastasis/anastasis-database/iterate_auth_iban_transfers.h"
#include "anastasis/anastasis-database/transaction.h"
#include "anastasis/anastasis-database/preflight.h"
#include <taler/taler_pq_lib.h>


struct TestIbanContext
{

  /**
   * Function to call on each wire transfer found.
   */
  ANASTASIS_DB_AuthIbanTransferCallback cb;

  /**
   * Closure for @a cb.
   */
  void *cb_cls;

  /**
   * Value to return.
   */
  enum GNUNET_DB_QueryStatus qs;
};


/**
 * Helper function for #postgres_test_auth_iban_payment().
 * To be called with the results of a SELECT statement
 * that has returned @a num_results results.
 *
 * @param cls closure of type `struct TestIbanContext *`
 * @param result the postgres result
 * @param num_results the number of results in @a result
 */
static void
test_auth_cb (void *cls,
              PGresult *result,
              unsigned int num_results)
{
  struct TestIbanContext *tic = cls;

  for (unsigned int i = 0; i<num_results; i++)
  {
    struct TALER_Amount credit;
    char *wire_subject;
    struct GNUNET_PQ_ResultSpec rs[] = {
      TALER_PQ_result_spec_amount ("credit",
                                   pg->currency,
                                   &credit),
      GNUNET_PQ_result_spec_string ("wire_subject",
                                    &wire_subject),
      GNUNET_PQ_result_spec_end
    };

    if (GNUNET_OK !=
        GNUNET_PQ_extract_result (result,
                                  rs,
                                  i))
    {
      GNUNET_break (0);
      tic->qs = GNUNET_DB_STATUS_HARD_ERROR;
      return;
    }
    if (tic->cb (tic->cb_cls,
                 &credit,
                 wire_subject))
    {
      GNUNET_free (wire_subject);
      tic->qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
      return;
    }
    GNUNET_free (wire_subject);
  }
}


/**
 * Function to check if we are aware of a wire transfer
 * that satisfies the IBAN plugin's authentication check.
 *
 * @param debit_account which debit account to check
 * @param earliest_date earliest date to check
 * @param cb function to call on all entries found
 * @param cb_cls closure for @a cb
 * @return transaction status,
 *    #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a cb
 *      returned 'true' once
 *    #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no
 *      wire transfers existed for which @a cb returned true
 */enum GNUNET_DB_QueryStatus
ANASTASIS_DB_iterate_auth_iban_transfers (
  const char *debit_account,
  struct GNUNET_TIME_Timestamp earliest_date,
  ANASTASIS_DB_AuthIbanTransferCallback cb,
  void *cb_cls)
{
  struct TestIbanContext tic = {
    .cb = cb,
    .cb_cls = cb_cls
  };
  struct GNUNET_PQ_QueryParam params[] = {
    GNUNET_PQ_query_param_string (debit_account),
    GNUNET_PQ_query_param_timestamp (&earliest_date),
    GNUNET_PQ_query_param_end
  };
  enum GNUNET_DB_QueryStatus qs;

  PREPARE ("iterate_auth_iban_transfers",
           "SELECT"
           " credit"
           ",wire_subject"
           " FROM anastasis_auth_iban_in"
           " WHERE debit_account_details=$1"
           "  AND execution_date>=$2;");
  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
                                             "iterate_auth_iban_transfers",
                                             params,
                                             &test_auth_cb,
                                             &tic);
  if (qs < 0)
    return qs;
  return tic.qs;
}


/* end of iterate_auth_iban_transfers.c */
