using Knoks.Api.Client;
using Knoks.Api.Nswag.Client;
using Knoks.Test.Integrations.Api.Tools;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using System.Linq;
using Xunit.Abstractions;


namespace Knoks.Test.Integrations.Nswag.Api
{
    public class GeneralControllerTests: IAsyncLifetime
    {
        public ApiClient ApiClient { get; }
        public HttpClient HttpClient { get; }
        public GeneralClient Client { get; }
        private readonly ITestOutputHelper output;
        public GeneralControllerTests(ITestOutputHelper output)
        {
            this.output = output;
            HttpClient = ApiTestServer.CreateClient();
            ApiClient = new ApiClient(ApiTestServer.ApiIndetifier, HttpClient);

            Client = new GeneralClient(HttpClient);
            Client.BaseUrl = "http://localhost:52281/";
        }
        public async Task InitializeAsync()
        {
            await ApiClient.AuthorizeApiConsumer();
        }

        public Task DisposeAsync()
        {
            HttpClient.Dispose();
            return Task.CompletedTask;
        }

        [Fact(DisplayName = "Get tags")]
        void GetTags()
        {
            var tags = Client.Tags(0);
            Assert.NotEmpty(tags.Result.Items);
            var tags1 = Client.Tags(1);
            Assert.NotEmpty(tags1.Result.Items);
            Assert.NotEqual(tags.Result.Items, tags1.Result.Items);
        }
        [Fact(DisplayName = "Get Currencies")]
        void GetCurrencies()
        {
            var currencies = Client.CurrenciesGet();
            Assert.NotEmpty(currencies.Result.Items);
            Assert.DoesNotContain(currencies.Result.Items, it => it.CurrencyName == null || it.Decimals == null || it.LongName == null || it.Code == null);
        }
        [Fact(DisplayName = "Get Exchanges")]
        void GetExchanges()
        {
            var exchanges = Client.Exchanges();
            Assert.Null(exchanges?.Error?.Msg);
            Assert.Contains(exchanges.Result.Items.SelectMany(it => it.CurrencyPairs), it => it.Currency1 == "USD" || it.Currency2 == "USD");
            Assert.DoesNotContain(exchanges.Result.Items, it => it.ExchangeId == null || it.ExchangeName == null || it.CurrencyPairs == null || !it.CurrencyPairs.Any());
            Assert.DoesNotContain(exchanges.Result.Items.SelectMany(it => it.CurrencyPairs), it => it.Currency1 == null || it.Currency2 == null || it.Currency == null || it.DisplayName == null);
        }
        [Fact(DisplayName = "Get Configs")]
        void GetConfigs()
        {
            var configs = Client.Configs();
            Assert.Contains(configs.Result.Keys, it => it.Contains("aximumDuration"));
        }
        [Fact(DisplayName = "Create User")]
        void CreateUser()
        {
            var args = new CreateUserArgs()
            {
                FirstName = "John",
                LastName = "Doh",
                LanguageId = 50,
                CountryId = 178,
                PhonePrefix = "1200",
                Phone = "1234567",
                Email = "dont" + new Random((int)DateTime.Now.Ticks).Next().ToString() + "@reply.com",
                Password = "gjRo'jk23",
                //BirthDate = new DateTime().AddYears(20),
                Gender = "1",
                IsUSTaxEntity = false,
                KycApproved = false,
                PhoneVerified = false,
                MailVerfied = false,
                TermsOfServiceChecked = false
            };
            var result = Client.NewUser(args);
            //output.WriteLine(result.ToJson());
            output.WriteLine("Error = " + result?.Error?.Msg);
            Assert.Null(result?.Error?.Id);
            output.WriteLine("Created user " + result.Result.UserId);
            var result2 = Client.NewUser(args);
            output.WriteLine("Error = " + result2?.Error?.Msg);
            Assert.NotNull(result2?.Error?.Id);
        }
        [Fact(DisplayName = "Create Wrong User")]
        async Task CreateWrongUser()
        {
            string email = "dont" + new Random((int)DateTime.Now.Ticks).Next().ToString() + "@reply.com";
            var args = new CreateUserArgs()
            {
                FirstName = "John",
                LastName = "Doh",
                LanguageId = 50,
                CountryId = 178,
                PhonePrefix = "1200",
                Phone = "1234567",
                Email = email,
                Password = "gjRo'jk23",
                //BirthDate = new DateTime().AddYears(20),
                Gender = "1",
                IsUSTaxEntity = false,
                KycApproved = false,
                PhoneVerified = false,
                MailVerfied = false,
                TermsOfServiceChecked = false
            };
            var result = Client.NewUser(args);
            Assert.Null(result?.Error?.Id);
            args.Phone = null;
            args.Email = "wrong" + email;
            var result2 = Client.NewUser(args);
            output.WriteLine("Error = " + result2?.Error?.Msg);
            Assert.NotNull(result2?.Error?.Id);
            args.Phone = "2345678";
            args.Email = "corrent" + email;
            var result3 = Client.NewUser(args);
            output.WriteLine("Error = " + result3?.Error?.Msg);
            Assert.Null(result3?.Error?.Id);

            await ApiClient.AuthorizeApiUser(email, args.Password);
            var userAccount1 = (await Knoks.Api.Client.Invoker.ApiInvoker.InvokeUserAccounts(ApiClient)).Object;
            await ApiClient.AuthorizeApiUser(args.Email, args.Password);
            var userAccount3 = (await Knoks.Api.Client.Invoker.ApiInvoker.InvokeUserAccounts(ApiClient)).Object;
            //Assert.Equal(userAccount1.Accounts.First().AccountId + 1, userAccount3.Accounts.First().AccountId); // Have no sence in parallel
        }

    }
}
