--
-- 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_do_insert_deposit_confirmation;
CREATE FUNCTION merchant_do_insert_deposit_confirmation (
  IN in_instance_id TEXT,
  IN in_h_contract_terms BYTEA,
  IN in_deposit_timestamp INT8,
  IN in_exchange_url TEXT,
  IN in_total_without_fee taler_amount_currency,
  IN in_wire_fee taler_amount_currency,
  IN in_h_wire BYTEA,
  IN in_exchange_sig BYTEA,
  IN in_exchange_pub BYTEA,
  IN in_wire_transfer_deadline INT8,
  IN in_notify_arg_str TEXT,
  OUT out_no_instance BOOL,
  OUT out_no_order BOOL,
  OUT out_no_account BOOL,
  OUT out_no_signkey BOOL,
  OUT out_conflict BOOL,
  OUT out_deposit_confirmation_serial INT8)
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_id INT8;
  my_order_serial INT8;
  my_account_serial INT8;
  my_signkey_serial INT8;
  my_record RECORD;
  my_bank_serial_id INT8;
  my_credit_amount taler_amount_currency;
BEGIN

out_no_instance=TRUE;
out_no_order=TRUE;
out_no_account=TRUE;
out_no_signkey=TRUE;
out_conflict=FALSE;
out_deposit_confirmation_serial=0;

-- Which instance are we using?
SELECT merchant_serial
  INTO my_merchant_id
  FROM merchant_instances
 WHERE merchant_id=in_instance_id;
IF NOT FOUND
THEN
  RETURN;
END IF;
out_no_instance=FALSE;

SELECT account_serial
  INTO my_account_serial
  FROM merchant_accounts
 WHERE merchant_serial=my_merchant_id
   AND h_wire=in_h_wire;
IF NOT FOUND
THEN
  RETURN;
END IF;
out_no_account=FALSE;

SELECT signkey_serial
  INTO my_signkey_serial
  FROM merchant_exchange_signing_keys
 WHERE exchange_pub=in_exchange_pub
 ORDER BY start_date DESC
 LIMIT 1;
IF NOT FOUND
THEN
  RETURN;
END IF;
out_no_signkey=FALSE;

SELECT order_serial
  INTO my_order_serial
  FROM merchant_contract_terms
 WHERE merchant_serial=my_merchant_id
   AND h_contract_terms=in_h_contract_terms;
IF NOT FOUND
THEN
  RETURN;
END IF;
out_no_order=FALSE;

SELECT deposit_confirmation_serial
   ,deposit_timestamp
   ,exchange_url
   ,total_without_fee
   ,wire_fee
   ,wire_transfer_deadline
   ,account_serial
  INTO my_record
  FROM merchant_deposit_confirmations
 WHERE order_serial=my_order_serial
   AND exchange_url=in_exchange_url;
IF NOT FOUND
THEN
  INSERT INTO merchant_deposit_confirmations
    (order_serial
    ,deposit_timestamp
    ,exchange_url
    ,total_without_fee
    ,wire_fee
    ,exchange_sig
    ,wire_transfer_deadline
    ,signkey_serial
    ,account_serial
  ) VALUES (
     my_order_serial
    ,in_deposit_timestamp
    ,in_exchange_url
    ,in_total_without_fee
    ,in_wire_fee
    ,in_exchange_sig
    ,in_wire_transfer_deadline
    ,my_signkey_serial
    ,my_account_serial
  ) RETURNING deposit_confirmation_serial
     INTO out_deposit_confirmation_serial;
ELSE
  IF (in_deposit_timestamp,
      in_wire_transfer_deadline,
      in_wire_fee,
      my_account_serial)
  IS DISTINCT FROM
     (my_record.deposit_timestamp,
      my_record.wire_transfer_deadline,
      my_record.wire_fee,
      my_record.account_serial)
  THEN
    out_conflict = TRUE;
    out_deposit_confirmation_serial = my_record.deposit_confirmation_serial;
    RETURN;
  END IF;
  IF ( ((in_total_without_fee).val < (my_record.total_without_fee).val) OR
       ( ((in_total_without_fee).val = (my_record.total_without_fee).val) AND
         ((in_total_without_fee).frac <= (my_record.total_without_fee).frac) ) )
  THEN
    -- new amount smaller or did not change, do NOT update.
    out_deposit_confirmation_serial = my_record.deposit_confirmation_serial;
    RETURN;
  END IF;

  -- Same deposit, but total amount increased, store this!
  UPDATE merchant_deposit_confirmations
    SET total_without_fee = in_total_without_fee
       ,exchange_sig = in_exchange_sig
       ,signkey_serial = my_signkey_serial;
  out_deposit_confirmation_serial = my_record.deposit_confirmation_serial;

END IF;

-- Do notify on TALER_DBEVENT_MERCHANT_NEW_WIRE_DEADLINE
PERFORM pg_notify ('XBZ19D98AK2REYNX93F736A56MT14SCY2EEX7XNXQMNCQ01B121R0',
                   in_notify_arg_str);

END $$;
