using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using MEU.API.Config;
using MEU.API.Logs;

namespace MEU.API.MiddleWare
{
    public class SignatureMiddleware 
    {
        private readonly RequestDelegate next;
        public SignatureMiddleware(RequestDelegate _next)
        {
            this.next = _next;
        }
        public static string MD5Signature(string input)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
            bs = x.ComputeHash(bs);
            System.Text.StringBuilder s = new System.Text.StringBuilder();
            foreach (byte b in bs)
            {
                s.Append(b.ToString("x2").ToLower());
            }
            return s.ToString();

        }
        public async Task Invoke(HttpContext context )
        {
            try
            {
                //var remoteIpAddress = context.Connection.RemoteIpAddress.ToString();
                //if (!ConfigEnvironment.ENVIRONMENT.ToLower().Trim().Equals("production"))
                //{
                //    if (!(remoteIpAddress == "27.74.255.96" || remoteIpAddress == "113.161.54.11"))
                //    {
                //        if (context.Request.Path.Value.ToString().ToLower().Contains("workflow"))
                //        {
                //            await context.Response.WriteAsync("Unknown");
                //        }                        
                //    }
                //}
                   

                if (ConfigEnvironment.ENVIRONMENT.ToLower().Trim().Equals("production"))
                {
                    if (!context.Request.Path.Value.ToString().ToLower().Contains("upload") &&
                        !context.Request.Path.Value.ToString().ToLower().Contains("notificationhub"))
                    {
                        string signature = context.Request.Headers["Signature"].ToString();
                        string time = context.Request.Headers["Time"].ToString();
                        string url = "." + context.Request.GetEncodedPathAndQuery();
                        string body = null;

                        if (context.Request.Method != HttpMethods.Get)
                        {
                            using (var reader = new StreamReader(
                            context.Request.Body,
                            encoding: Encoding.UTF8,
                            detectEncodingFromByteOrderMarks: false,
                            bufferSize: 1024 * 45,
                            leaveOpen: true))
                            {
                                body = await reader.ReadToEndAsync();
                                context.Request.Body.Position = 0;
                            }
                        }

                        if (string.IsNullOrEmpty(body))
                        {
                            body = "null";
                        }

                        object data = new
                        {
                            url = url,
                            body = body,
                            time = Int64.Parse(time)
                        };

                        string dataEncrypt = Newtonsoft.Json.JsonConvert.SerializeObject(data).ToLower() + "@123RAPTOR!@#&^";
                        string md5Data = MD5Signature(dataEncrypt);

                        if (signature != md5Data)
                        {
                            context.Response.Clear();
                            context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                            context.Response.Headers.Add("BACKEND_Signature", SignatureMiddleware.MD5Signature(md5Data));
                            if (dataEncrypt.Length < 500)
                            {
                                context.Response.Headers.Add("DATA", dataEncrypt);
                            }

                            await context.Response.WriteAsync("Forbiden");
                        }
                        else
                        {
                            await next(context);
                        }
                    }
                    else
                    {
                        await next(context);
                    }
                }
                else
                {
                    await next(context);
                }
            }
            catch (Exception ex)
            {
                context.Response.Clear();
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                LoggerFactory.ErrorLog(ex.ToString(), "Exception");
                await context.Response.WriteAsync("Forbiden");
            }
        }

    }
}