--
-- 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/>
--

SET search_path TO merchant;

DROP FUNCTION IF EXISTS merchant_do_increment_money_pots;
CREATE FUNCTION merchant_do_increment_money_pots (
  IN in_instance_id TEXT,
  IN ina_money_pots_ids INT8[],
  IN ina_increments taler_amount_currency[],
  OUT out_not_found BOOL)
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_id INT8;
  i INT;
  ini_current_pot_id INT8;
  ini_current_increment taler_amount_currency;
  my_totals taler_amount_currency[];
  currency_found BOOL;
  j INT;
BEGIN

SELECT merchant_serial
  INTO my_merchant_id
  FROM merchant_instances
  WHERE merchant_id=in_instance_id;

IF NOT FOUND
THEN
  out_not_found = TRUE;
  RETURN;
END IF;

out_not_found = FALSE;

IF ( COALESCE(array_length(ina_money_pots_ids, 1), 0) !=
     COALESCE(array_length(ina_increments, 1), 0) )
THEN
  RAISE EXCEPTION 'Array lengths must match';
END IF;

FOR i IN 1..COALESCE(array_length(ina_money_pots_ids, 1),0)
  LOOP
    ini_current_pot_id = ina_money_pots_ids[i];
    ini_current_increment = ina_increments[i];

    SELECT pot_totals
      INTO my_totals
      FROM merchant_money_pots
      WHERE money_pot_serial = ini_current_pot_id
        AND merchant_serial = my_merchant_id;

    IF NOT FOUND
    THEN
      -- If pot does not exist, we just ignore the entire
      -- requested increment, but update the return value.
      -- (We may have other pots to update, so we continue
      -- to iterate!).
      out_not_found = TRUE;
    ELSE
      -- Check if currency exists in pot_totals and update
      currency_found = FALSE;

      FOR j IN 1..COALESCE(array_length(my_totals, 1), 0)
      LOOP
        IF (my_totals[j]).currency = (ini_current_increment).currency
        THEN
          my_totals[j].frac
            = my_totals[j].frac + ini_current_increment.frac;
          my_totals[j].val
            = my_totals[j].val + ini_current_increment.val;
          IF my_totals[j].frac >= 100000000
          THEN
            my_totals[j].frac = my_totals[j].frac - 100000000;
            my_totals[j].val = my_totals[j].val + 1;
          END IF;
          currency_found = TRUE;
          EXIT; -- break out of loop
        END IF;
      END LOOP;

      IF NOT currency_found
      THEN
        my_totals = array_append(my_totals, ini_current_increment);
      END IF;

      UPDATE merchant_money_pots
        SET pot_totals = my_totals
        WHERE money_pot_serial = ini_current_pot_id
          AND merchant_serial = my_merchant_id;

    END IF;
  END LOOP;

END $$;
