using System;
using Xunit;
using Newtonsoft.Json.Linq;
using FluentAssertions;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;

namespace raven_integration
{
    //https://stackoverflow.com/questions/17725882/testing-asp-net-web-api-multipart-form-data-file-upload
    public class AttachmentTest
    {
        /// <summary>
        /// test attach CRUD
        /// </summary>       
        [Fact]
        public async void AttachmentUploadDownloadDeleteShouldWork()
        {

            //////////////////////////////////////////              
            //// Upload the files
            MultipartFormDataContent formDataContent = new MultipartFormDataContent();

            //Form data like the bizobject type and id
            formDataContent.Add(new StringContent("2"), name: "AttachToObjectType");
            formDataContent.Add(new StringContent("1"), name: "AttachToObjectId");
            //or if testing non-existant this is probably safe: long.MaxValue


            StreamContent file1 = new StreamContent(File.OpenRead($"{Util.TEST_DATA_FOLDER}\\test.png"));
            file1.Headers.ContentType = new MediaTypeHeaderValue("image/png");
            file1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            file1.Headers.ContentDisposition.FileName = "test.png";
            formDataContent.Add(file1);
            StreamContent file2 = new StreamContent(File.OpenRead($"{Util.TEST_DATA_FOLDER}\\test.zip"));
            file2.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
            file2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            file2.Headers.ContentDisposition.FileName = "test.zip";
            formDataContent.Add(file2);

            //create via inventory full test user as attachments use the role of the object attaching to
            ApiResponse a = await Util.PostFormDataAsync("Attachment", formDataContent, await Util.GetTokenAsync("InventoryFull"));


            Util.ValidateDataReturnResponseOk(a);


            long lTestPngAttachmentId = a.ObjectResponse["data"][0]["id"].Value<long>();
            long lTestZipAttachmentId = a.ObjectResponse["data"][1]["id"].Value<long>();

            //saw negative values on a db issue that I corrected (I think)
            //Keeping these in case it arises again, if it does, see log, it's a db error with async issue of some kind
            lTestPngAttachmentId.Should().BePositive();
            lTestZipAttachmentId.Should().BePositive();

            //////////////////////////////////////////              
            //// DOWNLOAD: Get the file attachment

            //Get the inventoryfull account download token
            // {
            //   "data": {
            //     "dlkey": "w7iE1cXF8kOxo8eomd1r8A",
            //     "expires": "2018-04-25T23:45:39.05665"
            //   }
            // }
            a = await Util.GetAsync("Attachment/DownloadToken", await Util.GetTokenAsync("InventoryFull"));
            Util.ValidateDataReturnResponseOk(a);
            string downloadToken = a.ObjectResponse["data"]["dlkey"].Value<string>();

            //now get the file  https://rockfish.ayanova.com/api/rfcaseblob/download/248?dlkey=9O2eDAAlZ0Wknj19SBK2iA
            var dlresponse = await Util.DownloadFileAsync("Attachment/Download/" + lTestZipAttachmentId.ToString() + "?dlkey=" + downloadToken, await Util.GetTokenAsync("InventoryFull"));

            //ensure it's the zip file we expected
            dlresponse.Content.Headers.ContentDisposition.FileName.Should().Be("test.zip");
            dlresponse.Content.Headers.ContentLength.Should().BeGreaterThan(2000);


            //////////////////////////////////////////              
            //// DELETE: Delete the file attachments
            ApiResponse d = await Util.DeleteAsync("Attachment/" + lTestPngAttachmentId.ToString(), await Util.GetTokenAsync("InventoryFull"));
            Util.ValidateHTTPStatusCode(d, 204);

            d = await Util.DeleteAsync("Attachment/" + lTestZipAttachmentId.ToString(), await Util.GetTokenAsync("InventoryFull"));
            Util.ValidateHTTPStatusCode(d, 204);


        }



        /// <summary>
        /// test no rights
        /// </summary>       
        [Fact]
        public async void NoRightsTest()
        {

            MultipartFormDataContent formDataContent = new MultipartFormDataContent();
         
            formDataContent.Add(new StringContent("2"), name: "AttachToObjectType");
            formDataContent.Add(new StringContent("1"), name: "AttachToObjectId");

            StreamContent file1 = new StreamContent(File.OpenRead($"{Util.TEST_DATA_FOLDER}\\test.png"));
            file1.Headers.ContentType = new MediaTypeHeaderValue("image/png");
            file1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            file1.Headers.ContentDisposition.FileName = "test.png";
            formDataContent.Add(file1);

            //ERROR CONDITION: BizAdminLimited user should not be able to attach a file to a widget
            ApiResponse a = await Util.PostFormDataAsync("Attachment", formDataContent, await Util.GetTokenAsync("BizAdminLimited"));

            //2004 unauthorized
            Util.ValidateErrorCodeResponse(a, 2004, 401);

        }


        /// <summary>
        /// test not attachable
        /// </summary>       
        [Fact]
        public async void UnattachableTest()
        {
            MultipartFormDataContent formDataContent = new MultipartFormDataContent();

            //Form data bizobject type and id

            //HERE IS THE ERROR CONDITION: LICENSE TYPE OBJECT WHICH IS UNATTACHABLE
            formDataContent.Add(new StringContent("5"), name: "AttachToObjectType");
            formDataContent.Add(new StringContent("1"), name: "AttachToObjectId");

            StreamContent file1 = new StreamContent(File.OpenRead($"{Util.TEST_DATA_FOLDER}\\test.png"));
            file1.Headers.ContentType = new MediaTypeHeaderValue("image/png");
            file1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            file1.Headers.ContentDisposition.FileName = "test.png";
            formDataContent.Add(file1);      
            ApiResponse a = await Util.PostFormDataAsync("Attachment", formDataContent, await Util.GetTokenAsync("InventoryFull"));

            //2203 unattachable object
            Util.ValidateErrorCodeResponse(a, 2203, 400);

        }


        /// <summary>
        /// test bad object values
        /// </summary>       
        [Fact]
        public async void BadObject()
        {
            MultipartFormDataContent formDataContent = new MultipartFormDataContent();

            //Form data like the bizobject type and id
            formDataContent.Add(new StringContent("2"), name: "AttachToObjectType");
            
            //HERE IS THE ERROR CONDITION, A NON EXISTENT ID VALUE FOR THE WIDGET
            formDataContent.Add(new StringContent(long.MaxValue.ToString()), name: "AttachToObjectId");//non-existent widget
            
            StreamContent file1 = new StreamContent(File.OpenRead($"{Util.TEST_DATA_FOLDER}\\test.png"));
            file1.Headers.ContentType = new MediaTypeHeaderValue("image/png");
            file1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            file1.Headers.ContentDisposition.FileName = "test.png";
            formDataContent.Add(file1);           
            ApiResponse a = await Util.PostFormDataAsync("Attachment", formDataContent, await Util.GetTokenAsync("InventoryFull"));

            //2203 invalid attachment object
            Util.ValidateErrorCodeResponse(a, 2203, 400);

        }






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

    }//eoc
}//eons
