using System;
using Xunit;
using Newtonsoft.Json.Linq;
using FluentAssertions;
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace raven_integration
{


    public class DataFilterOrderBy
    {
      
        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void DefaultSortByIdWorks()
        {

            var WidgetNameStart = Util.Uniquify("DefaultSortByIdWorks");

            //CREATE 3 TEST WIDGETS TO TEST ORDER
            long FirstInOrderWidgetId = 0;
            long SecondInOrderWidgetId = 0;
            long ThirdInOrderWidgetId = 0;

            dynamic w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            ApiResponse a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            ThirdInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            SecondInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            FirstInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();


            //CREATE FILTER
            dynamic d = new JObject();
            d.name = Util.Uniquify(WidgetNameStart);
            d["public"] = true;
            d.listKey = "widget";
            dynamic dfilter = new JArray();


            //name starts with filter to constrict to widgets that this test block created only
            dynamic DataFilterNameStart = new JObject();
            DataFilterNameStart.fld = "name";
            DataFilterNameStart.op = Util.OpStartsWith;
            DataFilterNameStart.value = WidgetNameStart;
            dfilter.Add(DataFilterNameStart);
            d.filter = dfilter.ToString();//it expects it to be a json string, not actual json

            a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("manager", "l3tm3in"), d.ToString());
            Util.ValidateDataReturnResponseOk(a);

            long DataFilterId = a.ObjectResponse["data"]["id"].Value<long>();

            //NOW FETCH WIDGET LIST WITH FILTER
            a = await Util.GetAsync($"Widget/listwidgets?Offset=0&Limit=999&DataFilterId={DataFilterId.ToString()}", await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateDataReturnResponseOk(a);
            Util.ValidateHTTPStatusCode(a, 200);

            //assert contains exactly 3 records
            ((JArray)a.ObjectResponse["data"]).Count.Should().Be(3);

            //assert the order returned
            a.ObjectResponse["data"][0]["id"].Value<long>().Should().Be(FirstInOrderWidgetId);
            a.ObjectResponse["data"][1]["id"].Value<long>().Should().Be(SecondInOrderWidgetId);
            a.ObjectResponse["data"][2]["id"].Value<long>().Should().Be(ThirdInOrderWidgetId);


            a = await Util.DeleteAsync("Widget/" + FirstInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + SecondInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + ThirdInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            //DELETE DATAFILTER
            a = await Util.DeleteAsync("DataFilter/" + DataFilterId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);
        }



        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void SortByFieldAscendingWorks()
        {

            var WidgetNameStart = Util.Uniquify("SortByFieldAscendingWorks");

            //CREATE 3 TEST WIDGETS TO TEST ORDER
            long FirstInOrderWidgetId = 0;
            long SecondInOrderWidgetId = 0;
            long ThirdInOrderWidgetId = 0;

            dynamic w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.startDate = DateTime.Now;
            w.endDate = DateTime.Now.AddHours(1);

            ApiResponse a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            FirstInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.startDate = DateTime.Now.AddHours(1);
            w.endDate = DateTime.Now.AddHours(2);
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            SecondInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.startDate = DateTime.Now.AddHours(2);
            w.endDate = DateTime.Now.AddHours(3);
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            ThirdInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();


            //CREATE FILTER
            dynamic d = new JObject();
            d.name = Util.Uniquify(WidgetNameStart);
            d["public"] = true;
            d.listKey = "widget";

            //FILTER IN BY NAME FOR TESTING THIS RUN ONLY
            dynamic dfilter = new JArray();
            //name starts with filter to constrict to widgets that this test block created only
            dynamic DataFilterNameStart = new JObject();
            DataFilterNameStart.fld = "name";
            DataFilterNameStart.op = Util.OpStartsWith;
            DataFilterNameStart.value = WidgetNameStart;
            dfilter.Add(DataFilterNameStart);
            d.filter = dfilter.ToString();

            //SORT ORDER ###################
            dynamic dsortarray = new JArray();
            dynamic dsort = new JObject();
            dsort.fld = "startdate";
            dsort.dir = "+";
            dsortarray.Add(dsort);
            d.sort = dsortarray.ToString();

            a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("manager", "l3tm3in"), d.ToString());
            Util.ValidateDataReturnResponseOk(a);

            long DataFilterId = a.ObjectResponse["data"]["id"].Value<long>();

            //NOW FETCH WIDGET LIST WITH FILTER
            a = await Util.GetAsync($"Widget/listwidgets?Offset=0&Limit=999&DataFilterId={DataFilterId.ToString()}", await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateDataReturnResponseOk(a);
            Util.ValidateHTTPStatusCode(a, 200);

            //assert contains exactly 3 records
            ((JArray)a.ObjectResponse["data"]).Count.Should().Be(3);

            //assert the order returned
            a.ObjectResponse["data"][0]["id"].Value<long>().Should().Be(FirstInOrderWidgetId);
            a.ObjectResponse["data"][1]["id"].Value<long>().Should().Be(SecondInOrderWidgetId);
            a.ObjectResponse["data"][2]["id"].Value<long>().Should().Be(ThirdInOrderWidgetId);


            a = await Util.DeleteAsync("Widget/" + FirstInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + SecondInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + ThirdInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            //DELETE DATAFILTER
            a = await Util.DeleteAsync("DataFilter/" + DataFilterId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

        }



        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void SortByFieldDescendingWorks()
        {

            var WidgetNameStart = Util.Uniquify("SortByFieldDescendingWorks");

            //CREATE 3 TEST WIDGETS TO TEST ORDER
            long FirstInOrderWidgetId = 0;
            long SecondInOrderWidgetId = 0;
            long ThirdInOrderWidgetId = 0;

            dynamic w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.count = 999;

            ApiResponse a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            FirstInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.count = 666;
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            SecondInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.count = 333;
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            ThirdInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();


            //CREATE FILTER
            dynamic d = new JObject();
            d.name = Util.Uniquify(WidgetNameStart);
            d["public"] = true;
            d.listKey = "widget";

            //FILTER IN BY NAME FOR TESTING THIS RUN ONLY
            dynamic dfilter = new JArray();
            //name starts with filter to constrict to widgets that this test block created only
            dynamic DataFilterNameStart = new JObject();
            DataFilterNameStart.fld = "name";
            DataFilterNameStart.op = Util.OpStartsWith;
            DataFilterNameStart.value = WidgetNameStart;
            dfilter.Add(DataFilterNameStart);
            d.filter = dfilter.ToString();

            //SORT ORDER ###################
            dynamic dsortarray = new JArray();
            dynamic dsort = new JObject();
            dsort.fld = "count";
            dsort.dir = "-";
            dsortarray.Add(dsort);
            d.sort = dsortarray.ToString();

            a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("manager", "l3tm3in"), d.ToString());
            Util.ValidateDataReturnResponseOk(a);

            long DataFilterId = a.ObjectResponse["data"]["id"].Value<long>();

            //NOW FETCH WIDGET LIST WITH FILTER
            a = await Util.GetAsync($"Widget/listwidgets?Offset=0&Limit=999&DataFilterId={DataFilterId.ToString()}", await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateDataReturnResponseOk(a);
            Util.ValidateHTTPStatusCode(a, 200);

            //assert contains exactly 3 records
            ((JArray)a.ObjectResponse["data"]).Count.Should().Be(3);

            //assert the order returned
            a.ObjectResponse["data"][0]["id"].Value<long>().Should().Be(FirstInOrderWidgetId);
            a.ObjectResponse["data"][1]["id"].Value<long>().Should().Be(SecondInOrderWidgetId);
            a.ObjectResponse["data"][2]["id"].Value<long>().Should().Be(ThirdInOrderWidgetId);


            a = await Util.DeleteAsync("Widget/" + FirstInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + SecondInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + ThirdInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            //DELETE DATAFILTER
            a = await Util.DeleteAsync("DataFilter/" + DataFilterId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

        }





        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void SortByMultipleFieldsWorks()
        {
            /*

            Created order:
            dollaramount, count
            2,1
            1,2
            2,2
            1,1


            sorted order:
            dollar asc, count desc
            1,2
            1,1
            2,2
            2,1

             */
            var WidgetNameStart = Util.Uniquify("SortByMultipleFieldsWorks");

            //CREATE 4 TEST WIDGETS TO TEST ORDER
            long FirstInOrderWidgetId = 0;
            long SecondInOrderWidgetId = 0;
            long ThirdInOrderWidgetId = 0;
            long FourthInOrderWidgetId = 0;

            dynamic w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.dollaramount = 2.22;
            w.count = 1;

            ApiResponse a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            FourthInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.dollaramount = 1.11;
            w.count = 2;
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            FirstInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.dollaramount = 1.11;
            w.count = 1;
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            SecondInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();

            w = new JObject();
            w.name = Util.Uniquify(WidgetNameStart);
            w.dollaramount = 2.22;
            w.count = 2;
            a = await Util.PostAsync("Widget", await Util.GetTokenAsync("manager", "l3tm3in"), w.ToString());
            Util.ValidateDataReturnResponseOk(a);
            ThirdInOrderWidgetId = a.ObjectResponse["data"]["id"].Value<long>();


            //CREATE FILTER
            dynamic d = new JObject();
            d.name = Util.Uniquify(WidgetNameStart);
            d["public"] = true;
            d.listKey = "widget";

            //FILTER IN BY NAME FOR TESTING THIS RUN ONLY
            dynamic dfilter = new JArray();
            //name starts with filter to constrict to widgets that this test block created only
            dynamic DataFilterNameStart = new JObject();
            DataFilterNameStart.fld = "name";
            DataFilterNameStart.op = Util.OpStartsWith;
            DataFilterNameStart.value = WidgetNameStart;
            dfilter.Add(DataFilterNameStart);
            d.filter = dfilter.ToString();

            //SORT ORDER ###################
            dynamic dsortarray = new JArray();

            //First column            
            dynamic dsort1 = new JObject();
            dsort1.fld = "dollaramount";
            dsort1.dir = "+";
            dsortarray.Add(dsort1);

            //Second column            
            dynamic dsort2 = new JObject();
            dsort2.fld = "count";
            dsort2.dir = "-";
            dsortarray.Add(dsort2);


            d.sort = dsortarray.ToString();

            a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("manager", "l3tm3in"), d.ToString());
            Util.ValidateDataReturnResponseOk(a);

            long DataFilterId = a.ObjectResponse["data"]["id"].Value<long>();

            //NOW FETCH WIDGET LIST WITH FILTER
            a = await Util.GetAsync($"Widget/listwidgets?Offset=0&Limit=999&DataFilterId={DataFilterId.ToString()}", await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateDataReturnResponseOk(a);
            Util.ValidateHTTPStatusCode(a, 200);

            //assert contains exactly 3 records
            ((JArray)a.ObjectResponse["data"]).Count.Should().Be(4);

            //assert the order returned
            a.ObjectResponse["data"][0]["id"].Value<long>().Should().Be(FirstInOrderWidgetId);
            a.ObjectResponse["data"][1]["id"].Value<long>().Should().Be(SecondInOrderWidgetId);
            a.ObjectResponse["data"][2]["id"].Value<long>().Should().Be(ThirdInOrderWidgetId);
            a.ObjectResponse["data"][3]["id"].Value<long>().Should().Be(FourthInOrderWidgetId);


            a = await Util.DeleteAsync("Widget/" + FirstInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + SecondInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + ThirdInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            a = await Util.DeleteAsync("Widget/" + FourthInOrderWidgetId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

            //DELETE DATAFILTER
            a = await Util.DeleteAsync("DataFilter/" + DataFilterId.ToString(), await Util.GetTokenAsync("manager", "l3tm3in"));
            Util.ValidateHTTPStatusCode(a, 204);

        }

        //========================================================================

    }//eoc
}//eons
