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

namespace raven_integration
{

    public class DataFilterCrud
    {

        /// <summary>
        /// Test all CRUD routes
        /// </summary>
        [Fact]
        public async void CRUD()
        {
            //CREATE
            dynamic d = new JObject();
            d.name = Util.Uniquify("Test DataFilter");
            // d.ownerId = 1L;
            d["public"] = true;
            d.listKey = "widget";

            //"[{fld:"name",op:"!=",value:"Notequaltothis"},{fld:"tags",op:"Eq",value:"[23,456,54]"}]
            dynamic dfilter = new JArray();
            dynamic df = new JObject();
            df.fld = "name";
            df.op = "%-";
            df.value = "Generic";//lots of seed widgets start with Generic
            dfilter.Add(df);

            d.filter = dfilter.ToString();//it expects it to be a json string, not actual json

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

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


            //RETRIEVE           
            //Get one
            a = await Util.GetAsync("DataFilter/" + Id.ToString(), await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateDataReturnResponseOk(a);
            a.ObjectResponse["data"]["name"].Value<string>().Should().StartWith("Test DataFilter");

            //Get as alternate user should work for public filter
            a = await Util.GetAsync("DataFilter/" + Id.ToString(), await Util.GetTokenAsync("SubContractorLimited"));
            Util.ValidateDataReturnResponseOk(a);
            a.ObjectResponse["data"]["name"].Value<string>().Should().StartWith("Test DataFilter");


            //UPDATE

            //PUT, make private
            d["public"] = false;
            d.name = Util.Uniquify("Put - Test DataFilter (privatized)");
            d.concurrencyToken = a.ObjectResponse["data"]["concurrencyToken"].Value<uint>();
            a = await Util.PutAsync("DataFilter/" + Id.ToString(), await Util.GetTokenAsync("BizAdminFull"), d.ToString());
            Util.ValidateHTTPStatusCode(a, 200);

            //check PUT worked
            a = await Util.GetAsync("DataFilter/" + Id.ToString(), await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateNoErrorInResponse(a);
            a.ObjectResponse["data"]["name"].Value<string>().Should().Be(d.name.ToString());


            //FETCH DISALLOWED
            //Get as alternate user should fail for private filter
            a = await Util.GetAsync("DataFilter/" + Id.ToString(), await Util.GetTokenAsync("SubContractorLimited"));
            Util.ValidateResponseNotFound(a);

            // //DELETE
            ApiResponse DELETETestResponse = await Util.DeleteAsync("DataFilter/" + Id.ToString(), await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateHTTPStatusCode(DELETETestResponse, 204);

        }

        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void InvalidListKeyShouldFail()
        {
            //CREATE
            dynamic d = new JObject();
            d.name = Util.Uniquify("Test DataFilter");
            // d.ownerId = 1L;
            d["public"] = true;
            d.listKey = "nonexistant";

            //"[{fld:"name",op:"!=",value:"Notequaltothis"},{fld:"tags",op:"Eq",value:"[23,456,54]"}]
            dynamic dfilter = new JArray();
            dynamic df = new JObject();
            df.fld = "name";
            df.op = "%-";
            df.value = "Generic";//lots of seed widgets start with Generic
            dfilter.Add(df);

            d.filter = dfilter.ToString();//it expects it to be a json string, not actual json

            ApiResponse a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("BizAdminFull"), d.ToString());
            Util.ValidateErrorCodeResponse(a, 2200, 400);
            Util.ShouldContainValidationError(a, "ListKey", "InvalidValue");

        }


        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void InvalidFieldNameShouldFail()
        {
            //CREATE
            dynamic d = new JObject();
            d.name = Util.Uniquify("Test DataFilter");
            // d.ownerId = 1L;
            d["public"] = true;
            d.listKey = "widget";

            //"[{fld:"name",op:"!=",value:"Notequaltothis"},{fld:"tags",op:"Eq",value:"[23,456,54]"}]
            dynamic dfilter = new JArray();
            dynamic df = new JObject();
            df.fld = "doesntexist";
            df.op = "%-";
            df.value = "Generic";//lots of seed widgets start with Generic
            dfilter.Add(df);

            d.filter = dfilter.ToString();//it expects it to be a json string, not actual json

            ApiResponse a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("BizAdminFull"), d.ToString());
            Util.ValidateErrorCodeResponse(a, 2200, 400);
            Util.ShouldContainValidationError(a, "Filter", "InvalidValue");

        }



        /// <summary>
        /// 
        /// </summary>
        [Fact]
        public async void InvalidOperatorShouldFail()
        {
            //CREATE
            dynamic d = new JObject();
            d.name = Util.Uniquify("Test DataFilter");
            // d.ownerId = 1L;
            d["public"] = true;
            d.listKey = "widget";

            //"[{fld:"name",op:"!=",value:"Notequaltothis"},{fld:"tags",op:"Eq",value:"[23,456,54]"}]
            dynamic dfilter = new JArray();
            dynamic df = new JObject();
            df.fld = "name";
            df.op = "wtf";
            df.value = "Generic";//lots of seed widgets start with Generic
            dfilter.Add(df);

            d.filter = dfilter.ToString();//it expects it to be a json string, not actual json

            ApiResponse a = await Util.PostAsync("DataFilter", await Util.GetTokenAsync("BizAdminFull"), d.ToString());
            Util.ValidateErrorCodeResponse(a, 2200, 400);
            Util.ShouldContainValidationError(a, "Filter", "InvalidValue");

        }



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

    }//eoc
}//eons
