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

DROP FUNCTION IF EXISTS do_insert_submitted_receipts;
CREATE FUNCTION do_insert_submitted_receipts(
  IN in_h_tax_number BYTEA,
  IN ina_h_donation_unit_pubs BYTEA[],
  IN ina_nonces BYTEA[],
  IN ina_donation_unit_sigs BYTEA[],
  IN in_donation_year INT8,
  --
  OUT out_conflict BOOL[],
  OUT out_unknown_du INT4
 )
LANGUAGE plpgsql
AS $$
DECLARE
  i INT4;
  ini_nonce BYTEA;
  ini_h_donation_unit_pub BYTEA;
  ini_donation_unit_sig BYTEA;
BEGIN

-- First pass: h_donation_unit_pub is client-supplied and is a foreign key
-- into donation_units.  'ON CONFLICT DO NOTHING' below absorbs unique
-- violations only, so an unknown donation unit would escape as SQLSTATE
-- 23503 -> HARD_ERROR -> HTTP 500, where 404 belongs.  Reject the whole
-- batch up front, before anything has been written.

-- out_unknown_du is 0 if every unit is known, otherwise the 1-based index
-- of the first unknown one.
out_unknown_du = 0;
FOR i IN 1..array_length(ina_h_donation_unit_pubs,1)
LOOP
  out_conflict[i] = FALSE;
  IF (out_unknown_du = 0)
  THEN
    PERFORM FROM donation_units
      WHERE h_donation_unit_pub=ina_h_donation_unit_pubs[i];
    IF NOT FOUND
    THEN
      out_unknown_du = i;
    END IF;
  END IF;
END LOOP;

IF (out_unknown_du > 0)
THEN
  RETURN;
END IF;

-- Insert each donation receipt

FOR i IN 1..array_length(ina_h_donation_unit_pubs,1)
LOOP
  ini_nonce = ina_nonces[i];
  ini_h_donation_unit_pub = ina_h_donation_unit_pubs[i];
  ini_donation_unit_sig = ina_donation_unit_sigs[i];

  INSERT INTO receipts_submitted
    (h_tax_number
    ,nonce
    ,h_donation_unit_pub
    ,donation_unit_sig
    ,donation_year
    )
    VALUES
    (in_h_tax_number
    ,ini_nonce
    ,ini_h_donation_unit_pub
    ,ini_donation_unit_sig
    ,in_donation_year
    )
    ON CONFLICT DO NOTHING;
  IF NOT FOUND
  THEN
    PERFORM FROM receipts_submitted
      WHERE h_tax_number=in_h_tax_number
        AND donation_unit_sig=ini_donation_unit_sig; -- if signature matches, everything must match
    out_conflict[i] = NOT FOUND;
  END IF;
END LOOP; -- end FOR all receipts

END $$;
