#!/bin/bash
# This file is part of TALER
# Copyright (C) 2014-2023 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/>
#

set -eu

# Replace with 0 for nexus...
USE_FAKEBANK=1
if [ 1 = "$USE_FAKEBANK" ]
then
    ACCOUNT="exchange-account-2"
    WIRE_METHOD="x-taler-bank"
    BANK_FLAGS="-f -d $WIRE_METHOD -u $ACCOUNT"
    BANK_URL="http://localhost:8082/"
else
    echo -n "Testing for libeufin-bank"
    libeufin-bank --help >/dev/null </dev/null || exit_skip " MISSING"
    echo " FOUND"

    ACCOUNT="exchange-account-1"
    WIRE_METHOD="iban"
    BANK_FLAGS="-ns -d $WIRE_METHOD -u $ACCOUNT"
    BANK_URL="http://localhost:18082/"
fi

. setup.sh


echo -n "Testing for taler-harness"
taler-harness --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"


# Launch system.
setup -c "test_template.conf" \
      -r "merchant-exchange-default" \
      -em \
      $BANK_FLAGS

LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX)
WALLET_DB=$(mktemp -p "${TMPDIR:-/tmp}" test_wallet.json-XXXXXX)
CONF="test_template.conf.edited"
if [ 1 = "$USE_FAKEBANK" ]
then
    FORTYTHREE="payto://x-taler-bank/localhost/fortythree?receiver-name=fortythree"
else
    FORTYTHREE=$(get_payto_uri fortythree x)
fi
EXCHANGE_URL="http://localhost:8081/"

echo -n "Configuring merchant instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer secret-token:super_secret' \
    "http://localhost:9966/management/instances" \
    -d '{"auth":{"method":"external"},"id":"admin","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204 No content, instance created. Got $STATUS instead"
fi

STATUS=$(curl -H "Content-Type: application/json" -X POST \
    -H 'Authorization: Bearer secret-token:super_secret' \
    http://localhost:9966/private/accounts \
    -d '{"payto_uri":"'"$FORTYTHREE"'"}' \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "200" ]
then
    exit_fail "Expected 200 OK. Got: $STATUS"
fi

echo "OK"

RANDOM_IMG='data:image/png;base64,abcdefg'
INFINITE_PRODUCT_TEMPLATE='{"product_id":"2","product_name":"stuff","description":"product with id 2 and price :15","unit_price":["TESTKUDOS:15"],"unit_total_stock":"-1","unit":"","image":"'"$RANDOM_IMG"'","taxes":[]}'
MANAGED_PRODUCT_TEMPLATE='{"product_id":"3","product_name":"more stuff","description":"product with id 3 and price :10","unit_price":["TESTKUDOS:150"],"unit_total_stock":"2","unit":"","image":"'"$RANDOM_IMG"'","taxes":[]}'

echo -n "Creating products..."
STATUS=$(curl 'http://localhost:9966/private/products' \
    -d "$INFINITE_PRODUCT_TEMPLATE" \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204, product created. got: $STATUS"
fi

STATUS=$(curl 'http://localhost:9966/private/products' \
    -d "$MANAGED_PRODUCT_TEMPLATE" \
    -w "%{http_code}" -s -o /dev/null)

if [ "$STATUS" != "204" ]
then
    exit_fail "Expected 204, product created. got: $STATUS"
fi
echo "OK"


PRODUCT_DATA=$(echo "$INFINITE_PRODUCT_TEMPLATE" | jq 'del(.product_id) | . + {description: "other description"}')

echo -n "Updating infinite stock product..."
STATUS=$(curl 'http://localhost:9966/private/products/2' -X PATCH \
    -d "$PRODUCT_DATA" \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "204" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 204, updating product. got: $STATUS"
fi

STATUS=$(curl 'http://localhost:9966/private/products/2' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

DESCRIPTION=$(jq -r .description < "$LAST_RESPONSE")

if [ "$DESCRIPTION" != "other description" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 'other description'. Got: $DESCRIPTION"
fi
echo "OK"

MANAGED_PRODUCT_ID=$(echo "$MANAGED_PRODUCT_TEMPLATE" | jq -r '.product_id')

echo -n "Locking inventory ..."

STATUS=$(curl "http://localhost:9966/private/products/${MANAGED_PRODUCT_ID}/lock" \
    -d '{"lock_uuid":"luck","duration":{"d_us": 100000000},"unit_quantity":"10"}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "410" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 410, lock failed. got: $STATUS"
fi

echo -n "."

STATUS=$(curl "http://localhost:9966/private/products/${MANAGED_PRODUCT_ID}/lock" \
    -d '{"lock_uuid":"luck","duration":{"d_us": 100000000},"unit_quantity":"1"}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "204" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 204, lock created. got: $STATUS"
fi
echo " OK"

echo -n "Creating order to be paid..."
STATUS=$(curl 'http://localhost:9966/private/orders' \
    -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"},"inventory_products":[{"product_id":"'"${MANAGED_PRODUCT_ID}"'","unit_quantity":"1"}]}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 200, order created. got: $STATUS"
fi

ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE")
#TOKEN=$(jq -e -r .token < "$LAST_RESPONSE")

STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 200, getting order info before claming it. got: $STATUS"
fi
PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE")

echo -n "."

STATUS=$(curl 'http://localhost:9966/private/orders' \
    -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"},"inventory_products":[{"product_id":"'"${MANAGED_PRODUCT_ID}"'","unit_quantity":"1"}]}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "410" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 410 out of stock (what remains is locked). got: $STATUS"
fi

echo -n "."

# Using the 'luck' inventory lock, order creation should work.
STATUS=$(curl 'http://localhost:9966/private/orders' \
    -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"},"lock_uuids":["luck"],"inventory_products":[{"product_id":"'"$MANAGED_PRODUCT_ID"'","unit_quantity":"1"}]}' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 200 OK, lock should apply. Got: $STATUS"
fi
echo " OK"

echo -n "First withdraw wallet ..."
rm -f "$WALLET_DB"
taler-wallet-cli \
    --no-throttle \
    --wallet-db="$WALLET_DB" \
    api \
    --expect-success 'withdrawTestBalance' \
  "$(jq -n '
    {
        amount: "TESTKUDOS:5",
        corebankApiBaseUrl: $BANK_URL,
        exchangeBaseUrl: $EXCHANGE_URL
    }' \
    --arg BANK_URL "$BANK_URL" \
    --arg EXCHANGE_URL "$EXCHANGE_URL"
  )" 2>wallet-withdraw-1.err >wallet-withdraw-1.out
echo -n "."
if [ 1 = "$USE_FAKEBANK" ]
then
    # Fakebank is instant...
    sleep 0
else
    sleep 10
    # NOTE: once libeufin can do long-polling, we should
    # be able to reduce the delay here and run wirewatch
    # always in the background via setup
fi
echo -n "."
taler-exchange-wirewatch -L "INFO" -c "$CONF" -t &> taler-exchange-wirewatch.out
echo -n "."

taler-wallet-cli \
    --wallet-db="$WALLET_DB" \
    run-until-done \
    2>wallet-withdraw-finish-1.err >wallet-withdraw-finish-1.out
echo " OK"

echo -n "Pay first order ..."
NOW=$(date +%s)
taler-wallet-cli \
    --no-throttle \
    --wallet-db="$WALLET_DB" \
    handle-uri "${PAY_URL}" \
    -y \
    2> wallet-pay1.err > wallet-pay1.log
NOW2=$(date +%s)
echo " OK (took $(( NOW2 -  NOW)) secs )"


STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 200 ok, after pay. got: $STATUS"
fi

ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE")

if [ "$ORDER_STATUS" != "paid" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 'paid'. got: $ORDER_STATUS"
fi


echo -n "Updating product..."

PRODUCT_DATA=$(echo "$MANAGED_PRODUCT_TEMPLATE" | jq 'del(.product_id) | . + {"total_stock": (.total_stock + 2) }')

STATUS=$(curl 'http://localhost:9966/private/products/3' -X PATCH \
    -d "$PRODUCT_DATA" \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "204" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 204, updating product. got: $STATUS"
fi

echo -n "Requesting inventory..."
STATUS=$(curl 'http://localhost:9966/private/products?name_filter=more' \
    -w "%{http_code}" -s -o "$LAST_RESPONSE")

if [ "$STATUS" != "200" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected 200. got: $STATUS"
fi

PRODUCT_COUNT=$(jq -r '.products|length' < "$LAST_RESPONSE")

if [ "$PRODUCT_COUNT" != "1" ]
then
    cat "$LAST_RESPONSE"
    exit_fail "Expected one product for the 'more'. filter, got: $PRODUCT_COUNT"
fi
echo " OK"

exit 0
