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

-- @file pg_statistics_example.sql
-- @brief example/test case for how to add statistics to the merchant backend, NOT for production!
-- @author Christian Grothoff

-- Everything in one big transaction
BEGIN;

-- Check patch versioning is in place.
-- SELECT _v.register_patch('example-statistics-0001', NULL, NULL);

CREATE SCHEMA IF NOT EXISTS example_statistics;

SET search_path TO example_statistics,merchant;


-- Setup statistic: what do we want to track for 'deposits'?
-- (Note: this is basically the one "manual" step we might not keep hard-coded)
INSERT INTO merchant_statistic_bucket_meta
  (slug
  ,description
  ,stype
  ,ranges
  ,ages)
VALUES
  ('deposits'
  ,'sales (before refunds)'
  ,'amount'
  ,ARRAY['second'::statistic_range, 'minute', 'day', 'month', 'quarter', 'year']
  ,ARRAY[120, 120, 95, 36, 40, 100] -- track last 120 s, 120 minutes, 95 days, 36 months, 40 quarters & 100 years
  )
ON CONFLICT DO NOTHING;

INSERT INTO merchant_statistic_interval_meta
  (slug
  ,description
  ,stype
  ,ranges
  ,precisions)
VALUES
  ('deposits'
  ,'sales (before refunds)'
  ,'amount'
  ,ARRAY(SELECT generate_series (1, 10, 1)) || ARRAY(SELECT generate_series (60, 180, 60)),
  ,array_fill (1, ARRAY[10]) || array_fill (5, ARRAY[3])
  ),
  ('products-sold'
  ,'number of products sold'
  ,'number'
  ,ARRAY(SELECT generate_series (1, 10, 1)) || [60],
  ,array_fill (1, ARRAY[10]) || [10]
  )
ON CONFLICT DO NOTHING;

DROP FUNCTION IF EXISTS merchant_deposits_statistics_trigger CASCADE;
CREATE FUNCTION merchant_deposits_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_instance INT8;
BEGIN
--  SET search_path TO merchant;
  SELECT mct.merchant_serial
    INTO my_instance
    FROM merchant_contract_terms mct
    JOIN merchant_deposit_confirmations mdc
      USING (order_serial)
    WHERE mdc.deposit_confirmation_serial = NEW.deposit_confirmation_serial;
  CALL merchant_do_bump_amount_stat
    ('deposits'
    ,my_instance
    ,CURRENT_TIMESTAMP(0)
    ,NEW.amount_with_fee);
  RETURN NEW;
END $$;
COMMENT ON FUNCTION merchant_deposits_statistics_trigger
  IS 'adds the deposited amount to the deposit statistics';

DO $$
DECLARE
  rec RECORD;
BEGIN
FOR rec IN
  SELECT 'deposits' AS in_slug
         ,mct.merchant_serial AS in_merchant_serial
         ,TO_TIMESTAMP (mdc.deposit_timestamp / 1000.0 / 1000.0)::TIMESTAMP AS in_timestamp
         ,mdc.total_without_fee AS in_delta
   FROM merchant_deposit_confirmations mdc
   JOIN merchant_contract_terms mct
     USING (order_serial)
   WHERE mdc.deposit_timestamp > (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0)) - 365*24*60*60) * 1000000
LOOP
   CALL merchant_do_bump_amount_stat (rec.in_slug, rec.in_merchant_serial, rec.in_timestamp, rec.in_delta);
END LOOP;
END $$;

-- Whenever a deposit is made, call our trigger to bump statistics
CREATE TRIGGER merchant_deposits_on_insert
  AFTER INSERT
    ON merchant_deposits
  FOR EACH ROW EXECUTE FUNCTION merchant_deposits_statistics_trigger();




-- Setup statistic
-- (Note: this is basically the one "manual" step we might not keep hard-coded)
INSERT INTO merchant_statistic_bucket_meta
  (slug
  ,description
  ,stype
  ,ranges
  ,ages)
VALUES
  ('products-sold'
  ,'products sold (only those tracked in inventory)'
  ,'number'
  ,ARRAY['second'::statistic_range, 'minute', 'day', 'week', 'month', 'quarter', 'year']
  ,ARRAY[120, 120, 60, 12, 24, 8, 10] -- track last 120s, 120 minutes, 60 days, 12 weeks, 24 months, 8 quarters and 10 years
  )
ON CONFLICT DO NOTHING;

DROP FUNCTION IF EXISTS merchant_products_sold_statistics_trigger CASCADE;
CREATE FUNCTION merchant_products_sold_statistics_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
  my_sold INT8;
BEGIN
--  SET search_path TO merchant;
  my_sold = NEW.total_sold - OLD.total_sold;
  IF (0 < my_sold)
  THEN
    CALL merchant_do_bump_number_stat
      ('products-sold'
      ,NEW.merchant_serial
      ,CURRENT_TIMESTAMP(0)
      ,my_sold);
  END IF;
  RETURN NEW;
END $$;

-- Whenever inventory changes, call our trigger to bump statistics
CREATE TRIGGER merchant_products_on_sold
  AFTER UPDATE
     ON merchant_inventory
  FOR EACH ROW EXECUTE FUNCTION merchant_products_sold_statistics_trigger();

delete from merchant.merchant_statistic_bucket_counter ;
delete from merchant.merchant_statistic_bucket_amount ;
delete from merchant.merchant_statistic_interval_counter;
delete from merchant.merchant_statistic_interval_amount;
delete from merchant.merchant_statistic_amount_event;
delete from merchant.merchant_statistic_counter_event;


call merchant_do_bump_number_stat ('products-sold'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP-INTERVAL '2 minutes', 1);
call merchant_do_bump_amount_stat ('deposits'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP-INTERVAL '2 minutes', (1,1,'EUR')::taler_amount_currency);
call merchant_do_bump_number_stat ('products-sold'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP-INTERVAL '2 seconds', 2);
call merchant_do_bump_amount_stat ('deposits'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP-INTERVAL '1 minute', (2,2,'EUR')::taler_amount_currency);
call merchant_do_bump_amount_stat ('deposits'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP-INTERVAL '2 seconds', (4,4,'EUR')::taler_amount_currency);
call merchant_do_bump_amount_stat ('deposits'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP-INTERVAL '1 second', (8,8,'EUR')::taler_amount_currency);
call merchant_do_bump_number_stat ('products-sold'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP, 4);
call merchant_do_bump_amount_stat ('deposits'::text, 6, CURRENT_TIMESTAMP(0)::TIMESTAMP, (16,16,'EUR')::taler_amount_currency);

select * from merchant_statistic_interval_number_get ('products-sold', 'default');

select * from merchant_statistic_interval_amount_get ('deposits', 'default');

select * from merchant.merchant_statistic_amount_event;

select * from merchant.merchant_statistic_counter_event;

select * from merchant.merchant_statistic_interval_counter;

select * from merchant.merchant_statistic_interval_amount;

select * from merchant.merchant_statistic_bucket_counter ;

select * from merchant.merchant_statistic_bucket_amount ;

-- ROLLBACK;
COMMIT;
