/*
  This file is part of TALER
  Copyright (C) 2025 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_units.c
 * @brief command to test POST /private/units
 * @author Bohdan Potuzhnyi
 */
#include "platform.h"
#include <taler/taler_testing_lib.h>
#include "taler_merchant_service.h"
#include "taler_merchant_testing_lib.h"


/**
 * State for a POST /private/units command.
 */
struct PostUnitState
{
  /**
   * In-flight request handle.
   */
  struct TALER_MERCHANT_UnitsPostHandle *uph;

  /**
   * Interpreter context.
   */
  struct TALER_TESTING_Interpreter *is;

  /**
   * Merchant backend base URL.
   */
  const char *merchant_url;

  /**
   * Unit identifier.
   */
  const char *unit_id;

  /**
   * Long label.
   */
  const char *unit_name_long;

  /**
   * Short label.
   */
  const char *unit_name_short;

  /**
   * Optional translations (reference counted).
   */
  json_t *unit_name_long_i18n;

  /**
   * Optional translations (reference counted).
   */
  json_t *unit_name_short_i18n;

  /**
   * Whether fractional quantities are allowed.
   */
  bool unit_allow_fraction;

  /**
   * Precision level for fractional quantities.
   */
  uint32_t unit_precision_level;

  /**
   * Whether the unit should be active.
   */
  bool unit_active;

  /**
   * Expected HTTP status.
   */
  unsigned int http_status;
};


/**
 * Completion callback for POST /private/units.
 */
static void
post_unit_cb (void *cls,
              const struct TALER_MERCHANT_HttpResponse *hr)
{
  struct PostUnitState *pus = cls;

  pus->uph = NULL;
  if (pus->http_status != hr->http_status)
  {
    TALER_TESTING_unexpected_status_with_body (pus->is,
                                               hr->http_status,
                                               pus->http_status,
                                               hr->reply);
    return;
  }
  TALER_TESTING_interpreter_next (pus->is);
}


/**
 * Issue the POST /private/units request.
 */
static void
post_unit_run (void *cls,
               const struct TALER_TESTING_Command *cmd,
               struct TALER_TESTING_Interpreter *is)
{
  struct PostUnitState *pus = cls;

  pus->is = is;
  pus->uph = TALER_MERCHANT_units_post (
    TALER_TESTING_interpreter_get_context (is),
    pus->merchant_url,
    pus->unit_id,
    pus->unit_name_long,
    pus->unit_name_short,
    pus->unit_allow_fraction,
    pus->unit_precision_level,
    pus->unit_active,
    pus->unit_name_long_i18n,
    pus->unit_name_short_i18n,
    &post_unit_cb,
    pus);
  if (NULL == pus->uph)
  {
    GNUNET_break (0);
    TALER_TESTING_interpreter_fail (is);
  }
}


/**
 * Provide traits for other commands.
 */
static enum GNUNET_GenericReturnValue
post_unit_traits (void *cls,
                  const void **ret,
                  const char *trait,
                  unsigned int index)
{
  struct PostUnitState *pus = cls;
  struct TALER_TESTING_Trait traits[] = {
    TALER_TESTING_make_trait_unit_id (pus->unit_id),
    TALER_TESTING_make_trait_unit_name_long (pus->unit_name_long),
    TALER_TESTING_make_trait_unit_name_short (pus->unit_name_short),
    TALER_TESTING_make_trait_unit_allow_fraction (&pus->unit_allow_fraction),
    TALER_TESTING_make_trait_unit_precision_level (&pus->unit_precision_level),
    TALER_TESTING_make_trait_unit_active (&pus->unit_active),
    TALER_TESTING_make_trait_unit_name_long_i18n (pus->unit_name_long_i18n),
    TALER_TESTING_make_trait_unit_name_short_i18n (pus->unit_name_short_i18n),
    TALER_TESTING_trait_end ()
  };

  return TALER_TESTING_get_trait (traits,
                                  ret,
                                  trait,
                                  index);
}


/**
 * Cleanup / cancel pending request.
 */
static void
post_unit_cleanup (void *cls,
                   const struct TALER_TESTING_Command *cmd)
{
  struct PostUnitState *pus = cls;

  if (NULL != pus->uph)
  {
    TALER_MERCHANT_units_post_cancel (pus->uph);
    pus->uph = NULL;
  }
  if (NULL != pus->unit_name_long_i18n)
    json_decref (pus->unit_name_long_i18n);
  if (NULL != pus->unit_name_short_i18n)
    json_decref (pus->unit_name_short_i18n);
  GNUNET_free (pus);
}


struct TALER_TESTING_Command
TALER_TESTING_cmd_merchant_post_units (const char *label,
                                       const char *merchant_url,
                                       const char *unit_id,
                                       const char *unit_name_long,
                                       const char *unit_name_short,
                                       bool unit_allow_fraction,
                                       uint32_t unit_precision_level,
                                       bool unit_active,
                                       json_t *unit_name_long_i18n,
                                       json_t *unit_name_short_i18n,
                                       unsigned int http_status)
{
  struct PostUnitState *pus;

  pus = GNUNET_new (struct PostUnitState);
  pus->merchant_url = merchant_url;
  pus->unit_id = unit_id;
  pus->unit_name_long = unit_name_long;
  pus->unit_name_short = unit_name_short;
  pus->unit_allow_fraction = unit_allow_fraction;
  pus->unit_precision_level = unit_precision_level;
  pus->unit_active = unit_active;
  pus->unit_name_long_i18n = unit_name_long_i18n;
  pus->unit_name_short_i18n = unit_name_short_i18n;
  pus->http_status = http_status;
  {
    struct TALER_TESTING_Command cmd = {
      .cls = pus,
      .label = label,
      .run = &post_unit_run,
      .cleanup = &post_unit_cleanup,
      .traits = &post_unit_traits
    };

    return cmd;
  }
}


/* end of testing_api_cmd_post_units.c */
