--
-- This file is part of TALER
-- Copyright (C) 2026 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/>
--

DROP FUNCTION IF EXISTS merchant.lookup_pending_deposits(TEXT, INT8, INT8, BOOLEAN);
CREATE FUNCTION merchant.lookup_pending_deposits(
  IN p_exchange_url TEXT,
  IN p_now INT8,
  IN p_limit INT8,
  IN p_allow_future BOOLEAN)
RETURNS TABLE(
  out_deposit_serial INT8,
  out_h_contract_terms BYTEA,
  out_merchant_priv BYTEA,
  out_merchant_id TEXT,
  out_wire_transfer_deadline INT8,
  out_retry_time INT8,
  out_h_wire BYTEA,
  out_amount_with_fee merchant.taler_amount_currency,
  out_deposit_fee merchant.taler_amount_currency,
  out_coin_pub BYTEA)
LANGUAGE plpgsql
AS $FN$
DECLARE
  rec RECORD;
  s TEXT;
  inner_rec RECORD;
  remaining INT8 := p_limit;
BEGIN
  FOR rec IN
    SELECT merchant_serial
          ,merchant_id
          ,merchant_priv
      FROM merchant.merchant_instances
  LOOP
    EXIT WHEN remaining <= 0;
    -- Instance was deleted: without its private key we cannot sign the
    -- tracking request, so its deposits can never be settled.
    CONTINUE WHEN rec.merchant_priv IS NULL;
    s := 'merchant_instance_' || rec.merchant_serial::TEXT;
    BEGIN
      FOR inner_rec IN
        EXECUTE format(
          'SELECT'
          '  md.deposit_serial AS deposit_serial'
          ' ,mct.h_contract_terms AS h_contract_terms'
          ' ,mdc.wire_transfer_deadline AS wire_transfer_deadline'
          ' ,md.settlement_retry_time AS retry_time'
          ' ,ma.h_wire AS h_wire'
          ' ,md.amount_with_fee AS amount_with_fee'
          ' ,md.deposit_fee AS deposit_fee'
          ' ,md.coin_pub AS coin_pub'
          ' FROM %I.merchant_deposits md'
          ' JOIN %I.merchant_deposit_confirmations mdc'
          '  USING (deposit_confirmation_serial)'
          ' JOIN %I.merchant_contract_terms mct'
          '  ON (mct.order_serial=mdc.order_serial)'
          ' JOIN %I.merchant_accounts ma'
          '  ON (mdc.account_serial=ma.account_serial)'
          ' LEFT JOIN %I.merchant_kyc kyc'
          '  ON (mdc.account_serial=kyc.account_serial)'
          ' WHERE (mdc.exchange_url=$1)'
          '  AND md.settlement_retry_needed'
          '  AND ($4 OR (md.settlement_retry_time < $2))'
          '  AND ( (kyc.kyc_ok IS NULL) OR kyc.kyc_ok)'
          ' ORDER BY md.settlement_retry_time ASC'
          ' LIMIT $3',
          s, s, s, s, s)
        USING p_exchange_url
             ,p_now
             ,remaining
             ,p_allow_future
      LOOP
        out_deposit_serial := inner_rec.deposit_serial;
        out_h_contract_terms := inner_rec.h_contract_terms;
        out_merchant_priv := rec.merchant_priv;
        out_merchant_id := rec.merchant_id;
        out_wire_transfer_deadline := inner_rec.wire_transfer_deadline;
        out_retry_time := inner_rec.retry_time;
        out_h_wire := inner_rec.h_wire;
        out_amount_with_fee := inner_rec.amount_with_fee;
        out_deposit_fee := inner_rec.deposit_fee;
        out_coin_pub := inner_rec.coin_pub;
        RETURN NEXT;
        remaining := remaining - 1;
        EXIT WHEN remaining <= 0;
      END LOOP;
    EXCEPTION
      WHEN undefined_table
      THEN
        NULL;
    END;
  END LOOP;
END
$FN$;
COMMENT ON FUNCTION merchant.lookup_pending_deposits(TEXT, INT8, INT8, BOOLEAN)
  IS 'Returns up to p_limit pending-settlement deposit rows for the given exchange'
     ' across all instance schemas, with merchant_priv read from'
     ' merchant.merchant_instances; instances whose private key was deleted'
     ' are skipped, as their deposits can no longer be settled.';
