using System;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using OnlineAssessment.Common;

namespace OnlineAssessment
{
    public class ErrorHandlingMiddleware
    {
        private readonly RequestDelegate next;
        public ErrorHandlingMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(HttpContext context /* other dependencies */)
        {
            try
            {
                await next(context);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(context, ex);
            }
        }

        private static Task HandleExceptionAsync(HttpContext context, Exception ex)
        {
            var code = HttpStatusCode.InternalServerError; // 500 if unexpected

            if (ex is FormatException) code = HttpStatusCode.BadRequest;
            else if (ex is InvalidOperationException) code = HttpStatusCode.BadRequest;
            else if (ex is UriFormatException) code = HttpStatusCode.RequestUriTooLong;
            else if (ex is UnauthorizedAccessException) code = HttpStatusCode.Unauthorized;
            else if (ex is ArgumentNullException) code = HttpStatusCode.BadRequest;
            else if (ex is ArgumentException) code = HttpStatusCode.BadRequest;
            else if (ex is WebException) code = HttpStatusCode.BadRequest;
            else if (ex is EntryPointNotFoundException) code = HttpStatusCode.NotFound;

            //else if (ex is ValueNotAcceptedException) code = HttpStatusCode.NotAcceptable;
            //else if (ex is UnauthorizedException) code = HttpStatusCode.Unauthorized;

            string retStatusMessage = string.Empty;
            string retStatusCode = (((int)code) * -1).ToString();

            if (ex.InnerException != null && ex.InnerException.Message.Length > 0)
            {
                retStatusMessage = string.Concat(ex.Message, " InnerException :- ", ex.InnerException.Message);
            }
            else
            {
                retStatusMessage = ex.Message;
            }

            ReturnResponse returnResponse = new ReturnResponse();
            ReturnStatus retStatus = new ReturnStatus(retStatusCode, retStatusMessage);

            returnResponse.Result = new object();
            returnResponse.Status = retStatus;

            //var result = JsonConvert.SerializeObject(new { code, error = ex.Message });
            var result = JsonConvert.SerializeObject(returnResponse);

            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)code;
            return context.Response.WriteAsync(result);
        }
    }
}
