using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json; //precisamos de uma biblioteca JSON. esta é a mais popular e é bem rápida.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace UnitTestMillenniumSDK
{
    public class MillenniumExceptionMessage
    {
        public string lang { get; set; }
        public string value { get; set; }
    }

    public class MillenniumExceptionMessageError
    {
        public MillenniumExceptionMessage message { get; set; }
        public string code { get; set; }
    }

    public class MillenniumExceptionResponse
    {
        public MillenniumExceptionMessageError error { get; set; }
    }

    public class MillenniumException : Exception
    {
        public MillenniumException(String Message, Exception Inner)
            : base(Message, Inner)
        {
            this.Source = "Millennium API call";
        }

        private static string ReadResponseMessage(WebException Inner)
        {
            if (Inner.Response.ContentType.Contains("json"))
            {
                var jsonstr = new StreamReader(Inner.Response.GetResponseStream(), Encoding.UTF8).ReadToEnd();
                var err = JsonConvert.DeserializeObject<MillenniumExceptionResponse>(jsonstr);
                if (err != null)
                    return err.error.message.value;
                else
                    return Inner.Message;
            }
            else
                return new StreamReader(Inner.Response.GetResponseStream()).ReadToEnd();
        }

        public MillenniumException(WebException Inner)
            : base(ReadResponseMessage(Inner), Inner)
        {
            this.Source = "Millennium API call";
        }
    }


    public class FILIAIS_LISTA_SIMPLES
    {
        public string NOME { get; set; }
    }

    public class FILIAIS_LISTA_SIMPLES_RESULTS
    {
        public List<FILIAIS_LISTA_SIMPLES> value { get; set; }
    }

    public class PRODUTO
    {
        public int produto;
        public string descricao1;
    }

    public class PRODUTO_LISTA_RESULTS
    {
        public List<PRODUTO> value { get; set; }
    }

    public class CLIENTES_ENDERECO
    {
        public string LOGRADOURO { get; set; }
        public string BAIRRO { get; set; }
        public string CIDADE { get; set; }
        public string ESTADO { get; set; }
    }

    public class CLIENTES_INCLUIROUALTERAR
    {
        public string COD_CLIENTE { get; set; }
        public string NOME { get; set; }
        public string CNPJ { get; set; }
        public string CPF { get; set; }
        public string PF_PJ { get; set; }
        public CLIENTES_ENDERECO ENDERECO { get; set; }
        public CLIENTES_ENDERECO ENDERECO_ENTREGA { get; set; }
    }

    public class CLIENTES_INCLUIROUALTERAR_RESULT
    {
        public int? COD_ENDERECO { get; set; }
        public int? CLIENTE { get; set; }
    }

    class WebClientEx : WebClient
    {
        protected override WebRequest GetWebRequest(Uri address)
        {
            HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
            request.AutomaticDecompression = DecompressionMethods.Deflate;
            return request;
        }
    }
    
    [TestClass]
    public class UnitTestMillenniumSDK
    {
        const string hostname = "millennium.iwise.com.br";
        const string port = "888";
        const string user = "odata";
        const string pass = "0d@t@123";
        const string domain = "MILLENNIUM-APP";       

        [TestMethod]
        public void ConsultaProdutos()
        {

            WebClientEx client = new WebClientEx();
            client.Headers["Content-type"] = "application/json"; //queremos retorno em json que é mais leve que xml
            client.Headers["DataServiceVersion"] = "3.0"; //preferimos versão 3.0 odata (default)            
            client.Encoding = Encoding.UTF8; //o resultado vem codificado em UTF8
            client.Proxy = null;
            client.Credentials = new NetworkCredential(user, pass, domain); //passamos as credenciais para acesso seguro ao servidor                       

            //vamos invocar o método no servidor               
            try
            {
                var resultado = JsonConvert.DeserializeObject<PRODUTO_LISTA_RESULTS>(client.DownloadString("http://" + hostname + ":" + port + "/api/millenium_eco/produtos/lista"));
                Assert.IsTrue(resultado.value.Count > 0);
            }
            catch (WebException e)
            {
                throw new MillenniumException(e);
            };
        }       

        [TestMethod]
        public void IncluiOuAlteraCliente()
        {

            WebClientEx client = new WebClientEx();            
            client.Headers["Content-type"] = "application/json"; //queremos retorno em json que é mais leve que xml
            client.Headers["DataServiceVersion"] = "3.0"; //preferimos versão 3.0 odata (default)            
            client.Encoding = Encoding.UTF8; //o resultado vem codificado em UTF8
            client.Proxy = null;                        
            client.Credentials = new NetworkCredential(user,pass,domain); //passamos as credenciais para acesso seguro ao servidor                       

            //vamos invocar o método no servidor      

            var cliente = new CLIENTES_INCLUIROUALTERAR();
            cliente.NOME = "CLIENTE DE TESTES";
            cliente.CPF = "999.999.999-99";            
            cliente.ENDERECO = new CLIENTES_ENDERECO();
            cliente.ENDERECO.BAIRRO = "BARRA FUNDA";
            cliente.ENDERECO.CIDADE = "SÃO PAULO";
            cliente.ENDERECO.LOGRADOURO = "RUA DE TESTES";
            cliente.ENDERECO.ESTADO = "SP";            

            try
            {
                var resultado = JsonConvert.DeserializeObject<CLIENTES_INCLUIROUALTERAR_RESULT>(client.UploadString("http://" + hostname + ":"+port+"/api/millenium_eco/clientes/IncluirOuAlterar",
                                        JsonConvert.SerializeObject(cliente)));

                Assert.IsTrue(resultado.CLIENTE != null);
                Assert.IsTrue(resultado.COD_ENDERECO != null);
            }
            catch (WebException e)
            {
                throw new MillenniumException(e);
            };            
        }       
    }
}
