/*
 This file is part of GNU Taler
 (C) 2019 GNUnet e.V.

 GNU 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.

 GNU 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
 GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

import test from "ava";

import { HostPortPath, PaytoType, Paytos } from "./payto.js";
import { Result } from "./result.js";

test("basic payto parsing", (t) => {
  const r1 = Paytos.fromString("https://example.com/");
  t.is(r1.tag, "error");

  const r2 = Paytos.fromString("payto:blabla");
  t.is(r2.tag, "error");

  // this doesn't work because x-taler-bank requires host and account
  const r3 = Paytos.fromString("payto:://x-taler-bank/12");
  t.is(r3.tag, "error");

  const r4 = Paytos.fromString("payto://x-taler-bank/host/account");
  if (r4.tag === "error") {
    t.fail();
    throw Error();
  }
  if (r4.value.targetType !== PaytoType.TalerBank) {
    t.fail(r4.value.targetType);
    throw Error();
  }
  t.is(r4.value.normalizedPath, "host/account");
});

test("basic x-taler-bank payto string", (t) => {
  const result = Result.unpack(
    Paytos.fromString("payto://x-taler-bank/bank.demo.taler.net/accountName"),
  );

  if (result.targetType !== PaytoType.TalerBank) {
    t.fail();
    throw Error();
  }
  t.is(result.normalizedPath, "bank.demo.taler.net/accountName");
  t.is(result.host, "bank.demo.taler.net");
  t.is(result.url, "https://bank.demo.taler.net/" as HostPortPath);
  t.is(result.account, "accountName");
});

test("parsing payto and stringify again on normalized strings are unchanged", (t) => {
  const payto1 = "payto://iban/DE1231231231?reciever-name=John%20Doe";
  t.is(
    Paytos.toFullString(Result.unpack(Paytos.fromString(payto1))),
    payto1 as Paytos.FullPaytoString,
  );

  const normalized = "payto://iban/DE1231231231";
  t.is(
    Paytos.toNormalizedString(Result.unpack(Paytos.fromString(payto1))),
    normalized as Paytos.NormalizedPaytoString,
  );
});
test("parsing payto and stringify again converts to the normal form", (t) => {
  const fullPayto_not_normalized =
    "payto://iban/de1231231231?reciever-name=John%20Doe";
  // after normalization the country code is uppercased
  const fullPayto_normalized =
    "payto://iban/DE1231231231?reciever-name=John%20Doe" as Paytos.FullPaytoString;
  t.is(
    Paytos.toFullString(
      Result.unpack(Paytos.fromString(fullPayto_not_normalized)),
    ),
    fullPayto_normalized,
  );

  const normalized_lowercase = "payto://iban/DE1231231231";
  const normalized_uppercase =
    "payto://iban/DE1231231231" as Paytos.NormalizedPaytoString;
  t.is(
    Paytos.toNormalizedString(
      Result.unpack(Paytos.fromString(normalized_lowercase)),
    ),
    normalized_uppercase,
  );
});
test("parsing payto with % carh", (t) => {
  const payto1 =
    "payto://iban/DE7763544441436?receiver-name=Test%20123%2B-%24%25%5E%3Cem%3Ehi%3C%2Fem%3E" as Paytos.FullPaytoString;

  t.is(Paytos.toFullString(Result.unpack(Paytos.fromString(payto1))), payto1);
});

test("adding payto query params", (t) => {
  const payto1 =
    "payto://iban/DE1231231231?receiver-name=John%20Doe" as Paytos.FullPaytoString;
  const p = Result.unpack(Paytos.fromString(payto1));

  p.params["foo"] = "42";

  t.deepEqual(
    Paytos.toFullString(p),
    "payto://iban/DE1231231231?receiver-name=John%20Doe&foo=42",
  );
});

test("basic cyclos payto string", (t) => {
  {
    const result = Result.unpack(
      Paytos.fromString(
        "payto://cyclos/demo.cyclos.org/31000163100000000?receiver-name=John%20Doe",
      ),
    );

    if (result.targetType !== PaytoType.Cyclos) {
      t.fail();
      throw Error();
    }
    t.is(result.normalizedPath, "demo.cyclos.org/31000163100000000");
    t.is(result.url, "https://demo.cyclos.org/" as HostPortPath);
    t.is(result.account, "31000163100000000");
    t.is(result.params["receiver-name"], "John Doe");
  }

  {
    const result = Result.unpack(
      Paytos.fromString(
        "payto://cyclos/communities.cyclos.org/utrecht/31000163100000000?receiver-name=John%20Doe",
      ),
    );

    if (result.targetType !== PaytoType.Cyclos) {
      t.fail();
      throw Error();
    }
    t.is(
      result.normalizedPath,
      "communities.cyclos.org/utrecht/31000163100000000",
    );
    t.is(result.url, "https://communities.cyclos.org/utrecht/" as HostPortPath);
    t.is(result.account, "31000163100000000");
    t.is(result.params["receiver-name"], "John Doe");
  }
});
