--
-- This file is part of TALER
-- Copyright (C) 2023, 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 exchange_do_insert_successor_measure;
CREATE FUNCTION exchange_do_insert_successor_measure(
  IN in_h_normalized_payto BYTEA,
  IN in_decision_time INT8,
  IN in_expiration_time INT8,
  IN in_new_measure_name TEXT, -- can be NULL
  IN in_jmeasures JSONB, -- can be NULL
  OUT out_last_date INT8,
  OUT out_account_unknown BOOLEAN,
  OUT out_legitimization_measure_serial_id INT8
)
LANGUAGE plpgsql
AS $$
DECLARE
  my_outcome_serial_id INT8;
  my_access_token BYTEA;
  my_is_wallet BOOL;
BEGIN

out_account_unknown=FALSE;
out_legitimization_measure_serial_id=0;

-- Check no more recent decision exists.
SELECT decision_time
  INTO out_last_date
  FROM legitimization_outcomes
 WHERE h_payto=in_h_normalized_payto
   AND is_active
 ORDER BY decision_time DESC, outcome_serial_id DESC;

IF FOUND
THEN
  IF out_last_date > in_decision_time
  THEN
    -- Refuse to insert older decision.
    RETURN;
  END IF;
  UPDATE legitimization_outcomes
     SET is_active=FALSE
   WHERE h_payto=in_h_normalized_payto
     AND is_active;
ELSE
  out_last_date = 0;
END IF;

SELECT access_token
  INTO my_access_token
  FROM kyc_targets
 WHERE h_normalized_payto=in_h_normalized_payto;

IF NOT FOUND
THEN
  IF in_payto_uri IS NULL
  THEN
    -- AML decision on an unknown account without payto_uri => fail.
    out_account_unknown=TRUE;
    RETURN;
  END IF;

  my_is_wallet
    = (LOWER (SUBSTRING (in_payto_uri, 22)) =
       'payto://taler-reserve/') OR
      (LOWER (SUBSTRING (in_payto_uri, 27)) =
       'payto://taler-reserve-http/');
  INSERT INTO kyc_targets
    (h_normalized_payto
    ,is_wallet)
    VALUES
    (in_h_normalized_payto
    ,my_is_wallet)
    RETURNING access_token
      INTO my_access_token;
  INSERT INTO wire_targets
    (wire_target_h_payto
    ,h_normalized_payto
    ,payto_uri)
    VALUES
    (in_h_full_payto
    ,in_h_normalized_payto
    ,in_payto_uri)
  ON CONFLICT DO NOTHING;
END IF;


-- First check if a perfectly equivalent legi measure
-- already exists, to avoid creating tons of duplicates.
SELECT legitimization_measure_serial_id
  INTO out_legitimization_measure_serial_id
  FROM legitimization_measures
  WHERE access_token=my_access_token
    AND jmeasures=in_jmeasures
    AND NOT is_finished;

IF NOT FOUND
THEN
  -- Enable new legitimization measure
  INSERT INTO legitimization_measures
    (access_token
    ,start_time
    ,jmeasures
    ,display_priority)
    VALUES
    (my_access_token
    ,in_decision_time
    ,in_jmeasures
    ,1)
    RETURNING
      legitimization_measure_serial_id
    INTO
      out_legitimization_measure_serial_id;
END IF;

-- AML decision: mark all other active measures finished!
UPDATE legitimization_measures
  SET is_finished=TRUE
  WHERE access_token=my_access_token
    AND NOT is_finished
    AND legitimization_measure_serial_id != out_legitimization_measure_serial_id;

UPDATE legitimization_outcomes
   SET is_active=FALSE
 WHERE h_payto=in_h_normalized_payto
   -- this clause is a minor optimization to avoid
   -- updating outcomes that have long expired.
   AND expiration_time >= in_decision_time;

INSERT INTO legitimization_outcomes
  (h_payto
  ,decision_time
  ,expiration_time
  ,jproperties
  ,new_measure_name
  ,to_investigate
  ,jnew_rules
  )
  VALUES
  (in_h_normalized_payto
  ,in_decision_time
  ,in_expiration_time
  ,'{}'::JSONB
  ,in_new_measure_name
  ,FALSE
  ,NULL
  )
  RETURNING
    outcome_serial_id
  INTO
    my_outcome_serial_id;

END $$;


COMMENT ON FUNCTION exchange_do_insert_successor_measure(BYTEA, INT8, INT8, TEXT, JSONB)
  IS 'Checks whether the AML officer is eligible to make AML decisions and if so inserts the decision into the table';
