-- Deploy camper:process_payment_response to pg
-- requires: roles
-- requires: schema_camper
-- requires: redsys_response
-- requires: payment
-- requires: payment_redsys_response
-- requires: parse_price
-- requires: currency

begin;

set search_path to camper, public;

create or replace function process_payment_response(payment_slug uuid, response redsys_response) returns text as
$$
declare
	pid integer;
	next_status text;
begin
	if response.transaction_type not in (0, 1, 2, 3, 9) then
		raise invalid_parameter_value using message = response.transaction_type || ' is not a processable transaction type';
	end if;

	select payment_id into pid from payment where slug = payment_slug;
	if pid is null then
		return '';
	end if;

	update payment
	set payment_status = case response.transaction_type
		when 0 then -- charge
			case when response.response_code < 100 then 'completed' else 'failed' end
		when 1 then -- authorization hold
			case when response.response_code < 100 then 'preauth' else 'failed' end
		when 2 then -- confirm authorization hold
			case when response.response_code = 900 then 'completed' else payment_status end
		when 3 then -- refund
			case when response.response_code = 900 then 'refunded' else payment_status end
		when 9 then -- void authorization hold
			case when response.response_code = 400 then 'voided' else payment_status end
		else
			payment_status
		end
	  , updated_at = current_timestamp
	where payment_id = pid
	  and (
		   (response.transaction_type in (0, 1) and payment_status in ('pending', 'failed'))
		or (response.transaction_type in (2, 9) and payment_status in ('preauth', 'failed'))
		or (response.transaction_type = 3 and payment_status = 'completed')
	)
	returning payment_status
	into next_status;

	insert into payment_redsys_response (
		  payment_id
		, response_code
		, date_time
		, secure_payment
		, transaction_type
		, amount
		, currency_code
		, order_number
		, authorization_code
		, merchant_code
		, terminal_number
		, error_code
	)
	select pid
	     , response.response_code
	     , response.date_time
	     , response.secure_payment
	     , response.transaction_type
	     , parse_price(response.amount, decimal_digits)
	     , response.currency_code
	     , response.order_number
	     , response.authorization_code
	     , response.merchant_code
	     , response.terminal_number
	     , response.error_code
	from currency
	where currency.currency_code = response.currency_code
	;

	return coalesce(next_status, '');
end;
$$
	language plpgsql
;

revoke execute on function process_payment_response(uuid, redsys_response) from public;
grant execute on function process_payment_response(uuid, redsys_response) to guest;
grant execute on function process_payment_response(uuid, redsys_response) to employee;
grant execute on function process_payment_response(uuid, redsys_response) to admin;

commit;
