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

namespace raven_integration
{

    public class EventLog
    {



        /// <summary>
        ///
        /// </summary>
        [Fact]
        public async void ObjectLogWorks()
        {
            //CRUD a widget and confirm it logs properly
            //http://localhost:7575/api/v8.0/EventLog/UserLog?AyType=3&AyId=1
            //http://localhost:7575/api/v8.0/EventLog/ObjectLog?AyType=2&AyId=242
            //http://localhost:7575/api/v8.0/EventLog/UserLog?AyType=3&AyId=1&StartDate=2018-08-23&EndDate=2018-08-24

            dynamic w = new JObject();
            w.name = Util.Uniquify("EventLog Test WIDGET");
            w.created = DateTime.Now.ToString();
            w.dollarAmount = 2.22m;
            w.active = true;
            w.roles = 0;

            ApiResponse r2 = await Util.PostAsync("Widget", await Util.GetTokenAsync("InventoryFull"), w.ToString());
            Util.ValidateDataReturnResponseOk(r2);
            long w2Id = r2.ObjectResponse["data"]["id"].Value<long>();

            ApiResponse EventLogResponse = await Util.GetAsync($"EventLog/ObjectLog?AyType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateHTTPStatusCode(EventLogResponse, 200);

            //NOTE:was failing here, for no reason that makes any sense it thinks there are two created events by two users for the same widget.
            //might have been some temporary bad code in the seeder at one point when I was experimenting with async stuff


            ((JArray)EventLogResponse.ObjectResponse["data"]).Count.Should().Be(1);//only one event so far
            EventLogResponse.ObjectResponse["data"][0]["date"].Value<DateTime>().Should().BeLessThan(new TimeSpan(1, 0, 0)).Before(DateTime.UtcNow);//should be less than one hour before now
            EventLogResponse.ObjectResponse["data"][0]["userId"].Should().NotBeNull();
            EventLogResponse.ObjectResponse["data"][0]["event"].Value<int>().Should().Be(1);//AyEvent 1 = created
            EventLogResponse.ObjectResponse["data"][0]["textra"].Should().BeNullOrEmpty();

            //Get current user doing modifications ID
            long CurrentUserId = EventLogResponse.ObjectResponse["data"][0]["userId"].Value<long>();

            //RETRIEVE

            //Get one
            ApiResponse r3 = await Util.GetAsync("Widget/" + w2Id.ToString(), await Util.GetTokenAsync("InventoryFull"));
            Util.ValidateDataReturnResponseOk(r3);
            r3.ObjectResponse["data"]["name"].Value<string>().Should().Be(w.name.ToString());

            EventLogResponse = await Util.GetAsync($"EventLog/ObjectLog?AyType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateHTTPStatusCode(EventLogResponse, 200);
            ((JArray)EventLogResponse.ObjectResponse["data"]).Count.Should().Be(2);
            EventLogResponse.ObjectResponse["data"][1]["date"].Value<DateTime>().Should().BeLessThan(new TimeSpan(1, 0, 0)).Before(DateTime.UtcNow);//should be less than one hour before now
            EventLogResponse.ObjectResponse["data"][1]["userId"].Should().NotBeNull();
            EventLogResponse.ObjectResponse["data"][1]["event"].Value<int>().Should().Be(2);//AyEvent 2 = retrieved
            EventLogResponse.ObjectResponse["data"][1]["textra"].Should().BeNullOrEmpty();



            //UPDATE
            //PUT

            //update w2id 
            w.name = Util.Uniquify("UPDATED VIA PUT EVENTLOG TEST WIDGET");
            w.OwnerId = 1;
            w.concurrencyToken = r2.ObjectResponse["data"]["concurrencyToken"].Value<uint>();
            ApiResponse PUTTestResponse = await Util.PutAsync("Widget/" + w2Id.ToString(), await Util.GetTokenAsync("InventoryFull"), w.ToString());
            Util.ValidateHTTPStatusCode(PUTTestResponse, 200);

            //check PUT worked
            ApiResponse checkPUTWorked = await Util.GetAsync("Widget/" + w2Id.ToString(), await Util.GetTokenAsync("InventoryFull"));
            Util.ValidateNoErrorInResponse(checkPUTWorked);
            checkPUTWorked.ObjectResponse["data"]["name"].Value<string>().Should().Be(w.name.ToString());
            uint concurrencyToken = PUTTestResponse.ObjectResponse["data"]["concurrencyToken"].Value<uint>();

            EventLogResponse = await Util.GetAsync($"EventLog/ObjectLog?AyType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateHTTPStatusCode(EventLogResponse, 200);
            ((JArray)EventLogResponse.ObjectResponse["data"]).Count.Should().Be(4);
            EventLogResponse.ObjectResponse["data"][2]["date"].Value<DateTime>().Should().BeLessThan(new TimeSpan(1, 0, 0)).Before(DateTime.UtcNow);//should be less than one hour before now
            EventLogResponse.ObjectResponse["data"][2]["userId"].Should().NotBeNull();
            EventLogResponse.ObjectResponse["data"][2]["event"].Value<int>().Should().Be(3);//AyEvent 3 = Modified
            EventLogResponse.ObjectResponse["data"][2]["textra"].Should().BeNullOrEmpty();


            //Check user log for basic accessibility
            EventLogResponse = await Util.GetAsync($"EventLog/UserLog?AyType=3&AyId={CurrentUserId}", await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateHTTPStatusCode(EventLogResponse, 200);
            ((JArray)EventLogResponse.ObjectResponse["data"]).Count.Should().BeGreaterOrEqualTo(4);//just one run of the above will be 4 events plus any others from other tests
            //Not sure of any easy way to assert the User log is correct other than the count as other tests running concurrently could easily skew this


            //DELETE
            ApiResponse DELETETestResponse = await Util.DeleteAsync("Widget/" + w2Id.ToString(), await Util.GetTokenAsync("InventoryFull"));
            Util.ValidateHTTPStatusCode(DELETETestResponse, 204);

            //All events should be cleared up on deletion with the sole exception of the deleted event
            EventLogResponse = await Util.GetAsync($"EventLog/ObjectLog?AyType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdminFull"));
            Util.ValidateHTTPStatusCode(EventLogResponse, 200);
            ((JArray)EventLogResponse.ObjectResponse["data"]).Count.Should().Be(1);
            EventLogResponse.ObjectResponse["data"][0]["date"].Value<DateTime>().Should().BeLessThan(new TimeSpan(1, 0, 0)).Before(DateTime.UtcNow);//should be less than one hour before now
            EventLogResponse.ObjectResponse["data"][0]["userId"].Should().NotBeNull();
            EventLogResponse.ObjectResponse["data"][0]["event"].Value<int>().Should().Be(0);//AyEvent 0 = deleted
            EventLogResponse.ObjectResponse["data"][0]["textra"].Value<string>().Should().Be(w.name.ToString());


        }

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

    }//eoc
}//eons
