using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using CafeTerrace.Models.Api;
using CafeTerrace.Utilities;
using RestSharp;
using Xamarin.Essentials;
using Xamarin.Forms.Internals;

namespace CafeTerrace.Services
{
    public class RestServiceExeption : Exception
    {
        public RestStatus Status { get; set; }

        public RestServiceExeption(string message, RestStatus status) : base(message)
        {
            Status = status;
        }
    }
    class RestService<T>
    {
        private RestClient _client;
        private RestRequest _request;
        public RestService(string BaseAddress)
        {
            _client = new RestClient(BaseAddress);
        }

        public async Task<RestServiceRespond<T>> RequestBody(string address, Method method, object body, bool authorize = false)
        {
            if (Xamarin.Essentials.Connectivity.NetworkAccess != NetworkAccess.Internet)
                return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.NotInternetError, RestStatus.NoInternat));
            try
            {
                _request = new RestRequest(address, method);
                if (authorize == true)
                    _request.AddHeader("Authorization", $"Bearer {Instance.LoginedUser.Token.Access_Token}");

                _request.AddJsonBody(body);
                _request.AddHeader("Accept", "application/json");
                var res = await _client.ExecuteAsync<RestServiceRespond<T>>(_request);
                if (res.StatusCode == HttpStatusCode.OK)
                {
                    if (res.Data!=null && res.Data.IsSuccess)
                    {
                            return res.Data;
                    }
                    if (res.Data == null)
                        return Newtonsoft.Json.JsonConvert.DeserializeObject<RestServiceRespond<T>>(res.Content);
                    else
                        return await Task.FromException<RestServiceRespond<T>>(
                            new RestServiceExeption(res.Data.Message, res.Data.StatusCode));
                }
                else if (res.StatusCode == HttpStatusCode.BadRequest)
                {
                    if (res.Data == null)
                        return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.NotInternetError, RestStatus.BadRequest));
                    else
                        return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(res.Data.Message, RestStatus.BadRequest));
                }
                else if (res.StatusCode == HttpStatusCode.Unauthorized)
                {
                    Plugin.Settings.CrossSettings.Current.Remove("LoginedUser");
                    return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.Unauthorized, RestStatus.UnAuthorized));
                }
                else
                {
                    return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.NotInternetError, RestStatus.Error));

                }
            }
            catch (RestServiceExeption e)
            {
                return await Task.FromException<RestServiceRespond<T>>(e);
            }

        }
        public async Task<RestServiceRespond<T>> RequestParameters(string address, Method method, Dictionary<string, string> param, bool authorize = false)
        {
            var con = Xamarin.Essentials.Connectivity.NetworkAccess;
            if (con != NetworkAccess.Internet)
            {
                return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.NotInternetError, RestStatus.NoInternat));
            }

            try
            {
                _request = new RestRequest(address, method);
                if (authorize == true)
                    _request.AddHeader("Authorization", $"Bearer {Instance.LoginedUser.Token.Access_Token}");
                param.ForEach(p => _request.AddParameter(p.Key, p.Value));
                var res = await _client.ExecuteAsync<RestServiceRespond<T>>(_request);
                if (res.StatusCode == HttpStatusCode.OK)
                {
                    var data = Newtonsoft.Json.JsonConvert.DeserializeObject<RestServiceRespond<T>>(res.Content);
                    if (res.Data == null)
                    {

                        if (data == null)
                            return await Task.FromException<RestServiceRespond<T>>(
                                new RestServiceExeption(AppResource.ServiceUnAvailabel, RestStatus.BadRequest));
                        else
                            return data;
                    }
                    else
                    {
                        if (res.Data.IsSuccess)
                            return res.Data;
                        else
                            return await Task.FromException<RestServiceRespond<T>>(
                                new RestServiceExeption(res.Data.Message, res.Data.StatusCode));
                    }
                }
                else if (res.StatusCode == HttpStatusCode.BadRequest)
                {
                    if (res.Data == null)
                        return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.NotInternetError, RestStatus.BadRequest));
                    else
                        return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(res.Data.Message, RestStatus.BadRequest));
                }
                else if (res.StatusCode == HttpStatusCode.Unauthorized)
                {
                    Instance.LoginedUser = null;
                    return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.Unauthorized, RestStatus.UnAuthorized));
                }
                else if (res.StatusCode == HttpStatusCode.ServiceUnavailable)
                {
                    return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.ServiceUnAvailabel, RestStatus.Error));
                }
                else
                {
                    return await Task.FromException<RestServiceRespond<T>>(new RestServiceExeption(AppResource.NotInternetError + res.Content, RestStatus.Error));

                }
            }
            catch (RestServiceExeption e)
            {
                return await Task.FromException<RestServiceRespond<T>>(e);
            }
        }
    }
}
