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

  TALER is free software; you can redistribute it and/or modify
  it under the terms of the GNU 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 General Public License for more details.

  You should have received a copy of the GNU General Public
  License along with TALER; see the file COPYING.  If not, see
  <http://www.gnu.org/licenses/>
*/
/**
 * @file testing_api_cmd_post_donau_instances.c
 * @brief command to test POST /donau request
 * @author Bohdan Potuzhnyi
 * @author Vlada Svirsh
 */

#include "platform.h"
#include <taler/taler_exchange_service.h>
#include <taler/taler_testing_lib.h>
#include "taler_merchant_service.h"
#include "taler_merchant_testing_lib.h"
#include "taler_merchant_donau.h"
#include <donau/donau_testing_lib.h>

/**
 * State of a "POST /donau" CMD.
 */
struct PostDonauState
{
  /**
   * Handle for a "POST donau" request.
   */
  struct TALER_MERCHANT_DonauInstancePostHandle *dph;

  /**
   * The interpreter state.
   */
  struct TALER_TESTING_Interpreter *is;

  /**
   * Base URL of the merchant serving the request.
   */
  const char *merchant_url;

  /**
   * Charity details.
   */
  struct TALER_MERCHANT_DONAU_Charity charity;

  /**
   * Merchant reference to fetch public key.
   */
  const char *merchant_reference;

  /**
   * Authentication token for the request.
   */
  const char *auth_token;

  /**
   * Expected HTTP response code.
   */
  unsigned int http_status;
};

/**
 * Callback for a POST /donau operation.
 *
 * @param cls closure for this function
 * @param hr response being processed
 */
static void
post_donau_cb (void *cls,
               const struct TALER_MERCHANT_HttpResponse *hr)
{
  struct PostDonauState *pds = cls;

  pds->dph = NULL;
  if (pds->http_status != hr->http_status)
  {
    TALER_TESTING_unexpected_status_with_body (
      pds->is,
      hr->http_status,
      pds->http_status,
      hr->reply);
    TALER_TESTING_interpreter_fail (pds->is);
    return;
  }

  switch (hr->http_status)
  {
  case MHD_HTTP_NO_CONTENT:
    break;
  case MHD_HTTP_BAD_REQUEST:
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "POST /donau returned BAD REQUEST: %s\n",
                json_dumps (hr->reply, JSON_INDENT (2)));
    break;
  case MHD_HTTP_UNAUTHORIZED:
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "POST /donau returned UNAUTHORIZED\n");
    break;
  case MHD_HTTP_NOT_FOUND:
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "POST /donau returned NOT FOUND\n");
    break;
  default:
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "Unhandled HTTP status %u for POST /donau\n",
                hr->http_status);
  }
  TALER_TESTING_interpreter_next (pds->is);
}


/**
 * Run the "POST /donau" CMD.
 *
 * @param cls closure.
 * @param cmd command being run now.
 * @param is interpreter state.
 */
static void
post_donau_run (void *cls,
                const struct TALER_TESTING_Command *cmd,
                struct TALER_TESTING_Interpreter *is)
{
  struct PostDonauState *pds = cls;

  pds->is = is;
  pds->charity.charity_url = TALER_TESTING_get_donau_url (is);
  if (NULL != pds->merchant_reference)
  {
    const struct TALER_TESTING_Command *mc;
    const struct TALER_MerchantPublicKeyP *merchant_pub;

    mc = TALER_TESTING_interpreter_lookup_command (is,
                                                   pds->merchant_reference);
    GNUNET_assert (NULL != mc);
    GNUNET_assert (GNUNET_OK ==
                   TALER_TESTING_get_trait_merchant_pub (mc,
                                                         &merchant_pub));
    pds->charity.charity_pub.eddsa_pub = merchant_pub->eddsa_pub;
  }

  pds->dph = TALER_MERCHANT_donau_instances_post (
    TALER_TESTING_interpreter_get_context (is),
    pds->merchant_url,
    &pds->charity,
    pds->auth_token,
    &post_donau_cb,
    pds);

  if (NULL == pds->dph)
  {
    GNUNET_break (0);
    TALER_TESTING_interpreter_fail (pds->is);
    return;
  }
}


/**
 * Free the state of a "POST /donau" CMD, and possibly
 * cancel a pending operation thereof.
 *
 * @param cls closure.
 * @param cmd command being run.
 */
static void
post_donau_cleanup (void *cls,
                    const struct TALER_TESTING_Command *cmd)
{
  struct PostDonauState *pds = cls;

  if (NULL != pds->dph)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "POST /donau operation did not complete\n");
    TALER_MERCHANT_donau_instances_post_cancel (pds->dph);
  }
  GNUNET_free (pds);
}


/**
 * Create a new testing command for POST /donau.
 */
struct TALER_TESTING_Command
TALER_TESTING_cmd_merchant_post_donau_instance (const char *label,
                                                const char *url,
                                                const char *merchant_reference,
                                                unsigned int
                                                expected_http_status,
                                                ...)
{
  struct PostDonauState *pds = GNUNET_new (struct PostDonauState);
  struct DONAU_CharityPublicKeyP *charity_pub = GNUNET_new (struct
                                                            DONAU_CharityPublicKeyP);

  struct TALER_Amount max_amount;
  struct TALER_Amount date_amount;

  const char*mamount = "EUR:100";
  const char*damount = "EUR:20";

  GNUNET_assert (GNUNET_OK ==
                 TALER_string_to_amount (mamount,
                                         &max_amount));

  GNUNET_assert (GNUNET_OK ==
                 TALER_string_to_amount (damount,
                                         &date_amount));

  {
    struct TALER_MERCHANT_DONAU_Charity charity = {
      .charity_url = "http://replaced.in.post_donau_run/",
      .name = "example",
      .charity_pub = *charity_pub,
      .charity_id = 1,
      .max_per_year = max_amount,
      .receipts_to_date = date_amount,
      .current_year = 2025
    };
    GNUNET_free (charity_pub);

    pds->merchant_reference = merchant_reference;
    pds->merchant_url = url;
    pds->charity = charity;
    pds->http_status = expected_http_status;
    pds->auth_token = NULL;

    {
      struct TALER_TESTING_Command cmd = {
        .cls = pds,
        .label = label,
        .run = &post_donau_run,
        .cleanup = &post_donau_cleanup
      };

      return cmd;
    }

  }
}