--
-- 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/>
--


CREATE OR REPLACE FUNCTION merchant_do_insert_product (
  IN in_instance_id TEXT,
  IN in_product_id TEXT,
  IN in_description TEXT,
  IN in_description_i18n BYTEA,
  IN in_unit TEXT,
  IN in_image TEXT,
  IN in_taxes BYTEA,
  IN in_price taler_amount_currency,
  IN in_total_stock INT8,
  IN in_address BYTEA,
  IN in_next_restock INT8,
  IN in_minimum_age INT4,
  IN ina_categories INT8[],
  OUT out_no_instance BOOL,
  OUT out_conflict BOOL,
  OUT out_no_cat INT8)
LANGUAGE plpgsql
AS $$
DECLARE
  my_merchant_id INT8;
  my_product_serial INT8;
  i INT8;
  ini_cat INT8;
BEGIN

-- 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
  out_no_instance=TRUE;
  out_conflict=FALSE;
  out_no_cat=NULL;
  RETURN;
END IF;
out_no_instance=FALSE;

INSERT INTO merchant_inventory
 (merchant_serial
 ,product_id
 ,description
 ,description_i18n
 ,unit
 ,image
 ,taxes
 ,price
 ,total_stock
 ,address
 ,next_restock
 ,minimum_age
) VALUES (
  my_merchant_id
 ,in_product_id
 ,in_description
 ,in_description_i18n
 ,in_unit
 ,in_image
 ,in_taxes
 ,in_price
 ,in_total_stock
 ,in_address
 ,in_next_restock
 ,in_minimum_age)
ON CONFLICT (merchant_serial, product_id) DO NOTHING
 RETURNING product_serial
 INTO my_product_serial;


IF NOT FOUND
THEN
  -- Check for idempotency
  SELECT product_serial
    INTO my_product_serial
    FROM merchant_inventory
  WHERE merchant_serial=my_merchant_id
    AND product_id=in_product_id
    AND description=in_description
    AND description_i18n=in_description_i18n
    AND unit=in_unit
    AND image=in_image
    AND taxes=in_taxes
    AND price=in_price
    AND total_stock=in_total_stock
    AND address=in_address
    AND next_restock=in_next_restock
    AND minimum_age=in_minimum_age;
  IF NOT FOUND
  THEN
    out_conflict=TRUE;
    out_no_cat=NULL;
    RETURN;
  END IF;

  -- Check categories match as well
  FOR i IN 1..COALESCE(array_length(ina_categories,1),0)
  LOOP
    ini_cat=ina_categories[i];

    PERFORM
      FROM merchant_product_categories
      WHERE product_serial=my_product_serial
        AND category_serial=ini_cat;
    IF NOT FOUND
    THEN
      out_conflict=TRUE;
      out_no_cat=NULL;
      RETURN;
    END IF;
  END LOOP;

  -- Also check there are no additional categories
  -- in either set.
  SELECT COUNT(*)
    INTO i
    FROM merchant_product_categories
    WHERE product_serial=my_product_serial;
  IF i != array_length(ina_categories,1)
  THEN
    out_conflict=TRUE;
    out_no_cat=NULL;
    RETURN;
  END IF;

  -- Is idempotent!
  out_conflict=FALSE;
  out_no_cat=NULL;
  RETURN;
END IF;
out_conflict=FALSE;


-- Add categories
FOR i IN 1..COALESCE(array_length(ina_categories,1),0)
LOOP
  ini_cat=ina_categories[i];

  INSERT INTO merchant_product_categories
   (product_serial
   ,category_serial)
  VALUES
   (my_product_serial
   ,ini_cat)
  ON CONFLICT DO NOTHING;

  IF NOT FOUND
  THEN
    out_no_cat=i;
    RETURN;
  END IF;
END LOOP;

-- Success!
out_no_cat=NULL;
END $$;
