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

BEGIN;
SET search_path TO libeufin_bank;

DROP TRIGGER IF EXISTS cashin_link ON libeufin_nexus.talerable_incoming_transactions;
DROP FUNCTION IF EXISTS cashin_link;

CREATE OR REPLACE FUNCTION cashin_link() 
RETURNS trigger 
LANGUAGE plpgsql AS $$
  DECLARE
    now_date INT8;
    local_amount libeufin_bank.taler_amount;
    local_subject TEXT;
    too_small BOOLEAN;
    balance_insufficient BOOLEAN;
    no_account BOOLEAN;
  BEGIN
    -- Only reserve transaction triggers cashin
    IF NEW.type != 'reserve' THEN
      RETURN NEW;
    END IF;

    SELECT (amount).val, (amount).frac, subject, execution_time
      INTO local_amount.val, local_amount.frac, local_subject, now_date
      FROM libeufin_nexus.incoming_transactions
      WHERE incoming_transaction_id = NEW.incoming_transaction_id;
    SET search_path TO libeufin_bank;
    SELECT out_too_small, out_balance_insufficient, out_no_account
      INTO too_small, balance_insufficient, no_account
      FROM libeufin_bank.cashin(now_date, NEW.metadata, local_amount, local_subject);
    SET search_path TO libeufin_nexus;

    -- Bounce on soft failures
    IF too_small THEN
      -- TODO bounce fees ?
      PERFORM bounce_incoming(
         NEW.incoming_transaction_id
        ,((local_amount).val, (local_amount).frac)::taler_amount
        ,libeufin_nexus.ebics_id_gen()
        ,now_date
        ,'amount too small to be converted'
      );
      RETURN NULL;
    END IF;

    -- Error on hard failures
    IF no_account THEN
      RAISE EXCEPTION 'cashin failed: missing exchange account';
    END IF;
    IF balance_insufficient THEN
      RAISE EXCEPTION 'cashin failed: admin balance insufficient';
    END IF;

    RETURN NEW;
  END;
$$;

CREATE OR REPLACE TRIGGER cashin_link BEFORE INSERT ON libeufin_nexus.talerable_incoming_transactions
    FOR EACH ROW EXECUTE FUNCTION cashin_link();

COMMIT;