using GMCabsDriverAssistant.Enums;
using GMCabsDriverAssistant.Models;
using GMCabsDriverAssistant.Models.Rydo;
using GMCabsDriverAssistant.Utils;
using GMCabsDriverAssistantSolution.Models.Rydo;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using static GMCabsDriverAssistant.Constants;

namespace GMCabsDriverAssistant.Services
{
    public class GMCabsDriverService
    {
        #region Fields

        #endregion

        #region Properties
        #endregion

        #region Constructor
        #endregion

        #region Methods

        public async Task<ValidateTokenResponseDto> ValidateAuthToken(string token, string fcmToken)
        {

            ValidateTokenResponseDto validateTokenResponseDto = new ValidateTokenResponseDto();
            Uri uri = new Uri($"{BASE_URL}/Auth/ValidateToken");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(new { token, fcmToken });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                validateTokenResponseDto = JsonSerializer.Deserialize<ValidateTokenResponseDto>(responseData, options);
            }
            return validateTokenResponseDto;
        }
        public async Task<LoginResponseDto> Login(LoginRequestDto loginRequestDto)
        {
            LoginResponseDto loginResponseDto = new LoginResponseDto();
            try
            {
                Uri uri = new Uri(string.Format(BASE_URL + "/Auth/Login", string.Empty));
                Console.WriteLine($"URI: {uri}");

                string json = JsonSerializer.Serialize(loginRequestDto);
                StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
                HttpClient _httpClient = new HttpClient();
                PutAppVersionInHeader(_httpClient);

                HttpResponseMessage response = await _httpClient.PostAsync(uri, content);

                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                loginResponseDto = JsonSerializer.Deserialize<LoginResponseDto>(responseData, options);

                if (response.IsSuccessStatusCode)
                {
                    // DO Nothing

                }
                else if (response.StatusCode == HttpStatusCode.BadRequest)
                {
                    //TODO
                    return loginResponseDto;
                }
                else if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    //TODO
                    return loginResponseDto;
                }

            }
            catch (Exception ex)
            {

                throw ex;
            }
            return loginResponseDto;
        }
        public async Task<EftposLoginResponse> EftposLogin(EftposLoginRequest eftposLoginRequest)
        {
            EftposLoginResponse eftposLoginResponse = new EftposLoginResponse();

            Uri uri = new Uri(string.Format(BASE_URL_RYDO_API + "/v1/account/eftpos-login", string.Empty));
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(eftposLoginRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                eftposLoginResponse = JsonSerializer.Deserialize<EftposLoginResponse>(responseData, options);
            }
            return eftposLoginResponse;
        }
        public async Task<UnreadCountResponseDto> GetUnreadNotificationCount(string appToken)
        {
            UnreadCountResponseDto unreadCountResponse = new UnreadCountResponseDto();
            var unreadNotificationCount = 0;

            Uri uri = new Uri($"{BASE_URL}/Notifications/UnreadCount?token={appToken}");

            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);

            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                unreadNotificationCount = JsonSerializer.Deserialize<int>(responseData, options);

                unreadCountResponse.StatusCode = Constant.SUCCESS_CODE;
                unreadCountResponse.UnreadNotificationCount = unreadNotificationCount;
            }
            else
            {
                if (response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    unreadCountResponse.StatusCode = Constant.UNAUTHORIZED_CODE;
                    unreadCountResponse.UnreadNotificationCount = unreadNotificationCount;
                }
                else
                {
                    unreadCountResponse.StatusCode = Constant.BADREQUEST_CODE;
                    unreadCountResponse.UnreadNotificationCount = unreadNotificationCount;
                }
            }

            return unreadCountResponse;
        }
        public async Task<List<Guid>> GetBookingAvailableCount(string accessToken, string driverId, double lat, double lng)
        {
            List<Guid> bookingIDs = null;

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{driverId}/available?latitude={lat}&longitude={lng}");
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                List<BookingDto> bookings = JsonSerializer.Deserialize<List<BookingDto>>(responseData);
                if (bookings != null)
                {
                    bookingIDs = new List<Guid>();
                    foreach (BookingDto booking in bookings) { bookingIDs.Add(booking.BookingId); }
                }
            }
            return bookingIDs;
        }
        public async Task<List<CouponDto>> GetCoupons(string appToken)
        {
            List<CouponDto> coupons = new List<CouponDto>();
            Uri uri = new Uri(string.Format(BASE_URL + "/Coupons?token=" + appToken, string.Empty));
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                coupons = JsonSerializer.Deserialize<List<CouponDto>>(responseData, options);
            }
            else if (response.StatusCode == HttpStatusCode.BadRequest)
            {
                //TODO
            }
            else if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                //TODO
            }

            return coupons;
        }
        public async Task<List<CouponHistoryDto>> GetCouponsHistory(string appToken)
        {
            List<CouponHistoryDto> couponsHistory = new List<CouponHistoryDto>();

            Uri uri = new Uri(string.Format(BASE_URL + "/Coupons/History?token=" + appToken, string.Empty));
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                couponsHistory = JsonSerializer.Deserialize<List<CouponHistoryDto>>(responseData, options);
            }
            else if (response.StatusCode == HttpStatusCode.BadRequest)
            {
                //TODO
            }
            else if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                //TODO
            }

            return couponsHistory;
        }
        public async Task<List<NotificationDto>> GetNotifications(string appToken)
        {
            List<NotificationDto> notifications = new List<NotificationDto>();
            try
            {
                Uri uri = new Uri(string.Format(BASE_URL + "/Notifications?token=" + appToken, string.Empty));
                Console.WriteLine($"URI: {uri}");

                HttpClient _httpClient = new HttpClient();
                PutAppVersionInHeader(_httpClient);
                HttpResponseMessage respose = await _httpClient.GetAsync(uri);
                if (respose != null)
                {
                    var options = new JsonSerializerOptions
                    {
                        PropertyNameCaseInsensitive = true
                    };
                    var responseData = await respose.Content.ReadAsStringAsync();
                    notifications = JsonSerializer.Deserialize<List<NotificationDto>>(responseData, options);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return notifications;
        }
        public async Task<bool> MarkNotificationAsViewed(string appToken, string notificationId)
        {
            Uri uri = new Uri($"{BASE_URL}/Notifications/NotificationViewed/{notificationId}?token={appToken}");
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);

            var response = await _httpClient.PutAsync(uri, null);

            return response.IsSuccessStatusCode;
        }
        public async Task<List<BookingDto>> GetBookings(string accessToken, Guid driverId, double lat, double lng)
        {
            List<BookingDto> bookings = new List<BookingDto>();

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{driverId}/available?latitude={lat}&longitude={lng}");
            Debug.WriteLine(uri);

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);

            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                bookings = JsonSerializer.Deserialize<List<BookingDto>>(responseData);
                //if (bookings.Count <= 0)
                //{
                //    uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{driverId}/available?future_bookings=1");
                //    _httpClient = new HttpClient();
                //    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                //    response = await _httpClient.GetAsync(uri);
                //    if (response.IsSuccessStatusCode)
                //    {
                //        var featureResponseData = await response.Content.ReadAsStringAsync();
                //        bookings = JsonSerializer.Deserialize<List<BookingDto>>(featureResponseData);
                //    }

                //}
            }
            bookings = bookings.OrderBy(x => x.FormmattedPickUpDateTime).ToList();
            return await Task.FromResult(bookings);
        }
        public async Task<AcceptDeclineBookingResponse> AcceptBooking(AcceptDeclineBookingRequest acceptBookingRequest, string accessToken, string bookingId)
        {
            AcceptDeclineBookingResponse acceptBookingResponse = new AcceptDeclineBookingResponse();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/accept");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(acceptBookingRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                acceptBookingResponse = JsonSerializer.Deserialize<AcceptDeclineBookingResponse>(responseData, options);
            }
            acceptBookingResponse.StatusCode = (int)response.StatusCode;
            acceptBookingResponse.Message = (string)response.ReasonPhrase;
            return acceptBookingResponse;
        }
        public async Task<AcceptDeclineBookingResponse> DeclineBooking(AcceptDeclineBookingRequest declineBookingRequest, string accessToken, string bookingId)
        {
            AcceptDeclineBookingResponse declineBookingResponse = new AcceptDeclineBookingResponse();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/decline");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(declineBookingRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            declineBookingResponse.StatusCode = (int)response.StatusCode;
            declineBookingResponse.Message = (string)response.ReasonPhrase;

            return declineBookingResponse;
        }
        public async Task<int> SendDriverLocation(string appToken, LocationUpdateRequestDto locationUpdateRequestDto)
        {
            Uri uri = new Uri($"{BASE_URL}/DriverAssistantApp/UpdateLocation?token={appToken}");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(locationUpdateRequestDto);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);

            return (int)response.StatusCode;
        }
        public async Task<int> SendDriverLocationTablet(LocationUpdateRequestDto locationUpdateRequestDto)
        {
            Uri uri = new Uri($"{BASE_URL}/DriverAssistantApp/UpdateLocationTablet");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(locationUpdateRequestDto);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);

            return (int)response.StatusCode;
        }
        public async Task<bool> UpdateSilentModeSetting(string appToken, SilentModeSettingRequest request)
        {
            Uri uri = new Uri($"{BASE_URL}/DriverAssistantApp/UpdateDriverAppSilentModeSetting?token={appToken}");
            string json = JsonSerializer.Serialize(request);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);

            return response.IsSuccessStatusCode;
        }
        public async Task<List<BookingDto>> GetAcceptedFutureBookings(string accessToken, Guid driverId)
        {
            List<BookingDto> bookings = new List<BookingDto>();

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{driverId}/accepted");
            Debug.WriteLine(uri);

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                bookings = JsonSerializer.Deserialize<List<BookingDto>>(responseData);
            }
            return await Task.FromResult(bookings);
        }
        public async Task<BookingDto> GetBookingDetails(string accessToken, Guid bookingId)
        {
            BookingDto booking = new BookingDto();

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/details");
            Debug.WriteLine(uri);

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                booking = JsonSerializer.Deserialize<BookingDto>(responseData);
            }

            return await Task.FromResult(booking);
        }
        public async Task<BookingDto> GetAcceptedOnDemandBookingForDriver(string accessToken, Guid driverId)
        {
            List<BookingDto> booking = new List<BookingDto>();

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{driverId}/accepted");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                booking = JsonSerializer.Deserialize<List<BookingDto>>(responseData);
            }

            // there can be only on accepted on demand booking so the below result will either be the only entry or null
            return await Task.FromResult(booking.FirstOrDefault()); 
        }
        public async Task<bool> UpdateProfile(string appToken, MultipartFormDataContent content)
        {
            Uri uri = new Uri($"{BASE_URL}/Driver/UpdateDriverDetails?token={appToken}");
            Debug.WriteLine(uri);

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);

            return response.IsSuccessStatusCode;
        }
        public async Task<bool> GenerateOtp(string mobileNumber)
        {
            Uri uri = new Uri($"{BASE_URL}/Auth/GenerateOtp?mobileNumber={mobileNumber}");
            Debug.WriteLine(uri);

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, null);

            return response.IsSuccessStatusCode;
        }
        public async Task<bool> VerifyOtp(string mobileNumber, string otp)
        {
            var isOtpValid = false;

            Uri uri = new Uri($"{BASE_URL}/Auth/VerifyOtp");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(new { mobileNumber, otp });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var responseData = await response.Content.ReadAsStringAsync();
                isOtpValid = bool.Parse(responseData);
            }

            return isOtpValid;
        }
        public async Task<bool> UpdateDriverPin(string mobileNumber, int pin)
        {
            Uri uri = new Uri($"{BASE_URL}/Auth/UpdateDriverPin");
            Debug.WriteLine(uri);

            string json = JsonSerializer.Serialize(new { mobileNumber, pin });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);

            return response.IsSuccessStatusCode;
        }
        public async Task<string> CouponScan(string appToken, string couponText)
        {
            Uri uri = new Uri($"{BASE_URL}/Driver/CouponScan?token={appToken}");
            string json = JsonSerializer.Serialize(new { couponText });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
            var status = await response.Content.ReadAsStringAsync();
            return status.ToString();
        }
        public async Task<int> VoucherScanedCount(string appToken, DateTime reportingDate)
        {
            var voucherScanedCount = 0;

            Uri uri = new Uri($"{BASE_URL}/Coupons/VouchersScannedCount?token={appToken}");
            string json = JsonSerializer.Serialize(new { reportingDate });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                voucherScanedCount = JsonSerializer.Deserialize<int>(responseData, options);
            }

            return voucherScanedCount;
        }
        public async Task<bool> LogoutDriverApp(string appToken, double lastLat, double lastLng)
        {
            Uri uri = new Uri($"{BASE_URL}/Auth/Logout?token={appToken}&lastLat={lastLat}&lastLng={lastLng}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PostAsync(uri, content);

            return response.IsSuccessStatusCode;
        }
        public async Task<bool> DeclineFutureBooking(string accessToken, String bookingId)
        {
            bool result = false;
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/release");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            StringContent content = new StringContent("", Encoding.UTF8, "application/json");
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                result = true;
            }
            return result;
        }
        public async Task<bool> CreateLightDriver(CreateLightDriverRequest createLightDriverRequest)
        {
            bool result = false;
            try
            {
                Uri uri = new Uri(string.Format(BASE_URL + "/Auth/CreateLightDriver", string.Empty));
                Console.WriteLine($"URI: {uri}");
                string json = JsonSerializer.Serialize(createLightDriverRequest);
                StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
                HttpClient _httpClient = new HttpClient();
                PutAppVersionInHeader(_httpClient);
                HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    result= true;
                }
                else if (response.StatusCode == HttpStatusCode.BadRequest)
                {
                    //TODO
                    result= false;
                }               

            }
            catch (Exception ex)
            {
                result = false;
            }
            return result;
        }
        public async Task<LocationVoucherDto> GetLocationVoucherByLocationID(string appToken, int issuedFromLocationID)
        {
            LocationVoucherDto locationVoucher = new LocationVoucherDto();
            Uri uri = new Uri(string.Format(BASE_URL + "/Coupons/GetLocationVoucherByLocationID?token=" + appToken+ "&issuedFromLocationID=" + issuedFromLocationID, string.Empty));
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                locationVoucher = JsonSerializer.Deserialize<LocationVoucherDto>(responseData, options);
            }
            else if (response.StatusCode == HttpStatusCode.BadRequest)
            {
                //TODO
            }
            else if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                //TODO
            }

            return locationVoucher;
        }
        public async Task<bool> ValidateAdminPassword(string adminPassword)
        {
            var isValidAdminPassword = false;
            Uri uri = new Uri(string.Format(BASE_URL + "/Auth/ValidateAdminPassword?adminPassword=" + adminPassword));
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                isValidAdminPassword = true;
            }
            else if (response.StatusCode == HttpStatusCode.BadRequest)
            {
                isValidAdminPassword = false;
            }           

            return isValidAdminPassword;
        }
        public async Task<bool> ValidateTaxiNumberInstallation(string taxiNumber)
        {
            var isValidAdminPassword = false;
            Uri uri = new Uri(string.Format(BASE_URL + "/DriverAssistantApp/ValidateTaxiNumberInstallation?taxiNumber=" + taxiNumber));
            Console.WriteLine($"URI: {uri}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                isValidAdminPassword = true;
            }
            else if (response.StatusCode == HttpStatusCode.BadRequest)
            {
                isValidAdminPassword = false;
            }

            return isValidAdminPassword;
        }
        public async Task<StartRideResponse> StartRiding(StartRideRequest startRideRequest, string accessToken, string bookingId)
        {
            StartRideResponse startRideResponse = new StartRideResponse();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/start-ride");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(startRideRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                startRideResponse = JsonSerializer.Deserialize<StartRideResponse>(responseData, options);
            }
            startRideResponse.StatusCode = (int)response.StatusCode;
            startRideResponse.Message = (string)response.ReasonPhrase;
            return startRideResponse;
        }
        public async Task<ApiResponseDto> SendMessage(MessageRequest messageRequest, string accessToken, string bookingId)
        {
            ApiResponseDto apiResponseDto = new ApiResponseDto();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/message");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(messageRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await _httpClient.PostAsync(uri, content);
            apiResponseDto.StatusCode = (int)response.StatusCode;
            apiResponseDto.Message = (string)response.ReasonPhrase;
            return apiResponseDto;
        }
        public async Task<ApiResponseDto> ReleaseBooking(string accessToken, string bookingId)
        {
            ApiResponseDto apiResponseDto = new ApiResponseDto();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/release");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await _httpClient.PutAsync(uri, content);
            apiResponseDto.StatusCode = (int)response.StatusCode;
            apiResponseDto.Message = (string)response.ReasonPhrase;
            return apiResponseDto;
        }
        public async Task<ApiResponseDto> NoShowBooking(string accessToken, string bookingId)
        {
            ApiResponseDto apiResponseDto = new ApiResponseDto();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/no-show");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await _httpClient.PutAsync(uri, content);
            apiResponseDto.StatusCode = (int)response.StatusCode;
            apiResponseDto.Message = (string)response.ReasonPhrase;
            return apiResponseDto;
        }
        public async Task<int> NotifyStop(int stopNumber, string accessToken, string bookingId)
        {
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/notify-stop?stop_number={stopNumber}");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            return (int)response.StatusCode;
        }
        public async Task<ApiResponseDto> EndRiding(EndRideRequestDto endRideRequestDto, string accessToken, string bookingId)
        {
            ApiResponseDto apiResponseDto = new ApiResponseDto();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/end-ride");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(endRideRequestDto);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await _httpClient.PutAsync(uri, content);
            apiResponseDto.StatusCode = (int)response.StatusCode;
            apiResponseDto.Message = (string)response.ReasonPhrase;
            return apiResponseDto;
        }
        public async Task<ApiResponseDto> MakePaymentAtTerminal(string bookingId, string driverId, int amount)
        {
            ApiResponseDto apiResponseDto = new ApiResponseDto();
            Uri uri = new Uri(string.Format(BASE_URL + "/Terminal/PayAtTerminal?bookingID=" +  bookingId  + "&driverID=" + driverId + "&amount=" + amount));
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);
            apiResponseDto.StatusCode = (int)response.StatusCode;
            apiResponseDto.Message = (string)response.ReasonPhrase;
            return apiResponseDto;
        }
        public async Task<bool> CloseAccountDriverApp(string appToken)
        {
            Uri uri = new Uri($"{BASE_URL}/Driver/CloseAccount?token={appToken}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);

            return response.IsSuccessStatusCode;
        }
        public async Task<string> UpdateBookingStatus(string appToken, int statusFlag, bool isMetered)
        {
            Uri uri = new Uri(string.Format(BASE_URL + $"/DriverAssistantApp/MeterTripStatus?token={appToken}&statusFlag={statusFlag}&isMetered={isMetered}"));
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);
            var suburbName = (response.StatusCode == HttpStatusCode.OK) ? await response.Content.ReadAsStringAsync() : String.Empty;
            return suburbName.ToString();
        }
        public async Task<bool> DriverDistress(string appToken, double lat, double lng)
        {
            bool result = false;
            Uri uri = new Uri(string.Format(BASE_URL + $"/DriverAssistantApp/DriverDistress?token={appToken}&lat={lat}&lng={lng}"));
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                result = true;
            }
            return result;
        }
        public async Task<bool> RequestPayment(string appToken, int amount)
        {
            Uri uri = new Uri(string.Format(BASE_URL + "/DriverAssistantApp/RequestPayment?token=" + appToken + "&amount=" + amount));
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);

            return response.IsSuccessStatusCode;
        }
        public async Task<List<ImeiDto>> GetAvailableImeiNumbers(string enteredValue)
        {
            List<ImeiDto> imeiNumers = null;
            Uri uri = new Uri($"{BASE_URL}/TabletDevice/UninstalledImeis?enteredValue={enteredValue}");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                if (responseData != string.Empty)
                {
                    imeiNumers = JsonSerializer.Deserialize<List<ImeiDto>>(responseData,options);
                }
            }
            return imeiNumers;
        }
        // now done on logon
        //public async Task<bool> CompleteInstallation(string imeiValue)
        //{
        //    bool result = false;
        //    Uri uri = new Uri($"{BASE_URL}/TabletDevice/CompleteTabletInstall?imei={imeiValue}");
        //    string json = JsonSerializer.Serialize(new { });
        //    StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
        //    HttpClient _httpClient = new HttpClient();
        //    var response = await _httpClient.PutAsync(uri, content);

        //    if (response.IsSuccessStatusCode)
        //    {
        //        // need to handle a false in content result which means some other device has already been installed in the selected taxi

        //        result = true;
        //    }
        //    return result;
        //}
        public async Task<List<TripsBookingResponse>> GetTripDetails(string appToken)
        {
            List<TripsBookingResponse> tripsBookingResponses = new List<TripsBookingResponse>();

            Uri uri = new Uri(string.Format(BASE_URL + "/DriverAssistantApp/Trips?token=" + appToken));

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                tripsBookingResponses = JsonSerializer.Deserialize<List<TripsBookingResponse>>(responseData, options);
            }

            return tripsBookingResponses;
        }
        public async Task<AccountBalanceDto> GetLevyBalance(string appToken)
        {
            AccountBalanceDto accountBalanceDto = new AccountBalanceDto();

            Uri uri = new Uri(string.Format(BASE_URL + "/Driver/AccountBalance?token=" + appToken));

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);

            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                accountBalanceDto = JsonSerializer.Deserialize<AccountBalanceDto>(responseData, options);
            }

            return accountBalanceDto;
        }
        public async Task<DriverRatingResponse> GetDriverRatings(string accessToken, string driverId, string phoneNumber)
        {
            DriverRatingResponse driverRatingResponse = new DriverRatingResponse();

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/drivers?id={driverId}&phone_number={phoneNumber}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                driverRatingResponse = JsonSerializer.Deserialize<DriverRatingResponse>(responseData, options);
            }
            return driverRatingResponse;
        }
        public async Task<List<ShiftResponseDto>> GetShiftDetails(string appToken)
        {
            List<ShiftResponseDto> shiftResponses = new List<ShiftResponseDto>();

            Uri uri = new Uri(string.Format(BASE_URL + "/DriverAssistantApp/Shifts?token=" + appToken));

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                shiftResponses = JsonSerializer.Deserialize<List<ShiftResponseDto>>(responseData, options);
            }

            return shiftResponses;
        }

        public async Task<List<PlotResponseDto>> GetAvailablePlot(string accessToken, string driverId, double lat, double lng)
        {
            List<PlotResponseDto> plotResponses = new List<PlotResponseDto>();

            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/available-plot?driver_id={driverId}&lat={lat}&lng={lng}");

            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                plotResponses = JsonSerializer.Deserialize<List<PlotResponseDto>>(responseData, options);
            }
            return plotResponses;
        }
        public async Task<AvailablePlotResponseDto> GetPlottedDriverInformation(AvailablePlotRequestDto availablePlotRequest, string accessToken)
        {
            AvailablePlotResponseDto availablePlotResponse = new AvailablePlotResponseDto();

            Uri uri = new Uri(string.Format(BASE_URL_RYDO_API + "/v1/bookings/driver-plot", string.Empty));
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(availablePlotRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                availablePlotResponse = JsonSerializer.Deserialize<AvailablePlotResponseDto>(responseData, options);
                availablePlotResponse.apiResponseDto = new ApiResponseDto();
                availablePlotResponse.apiResponseDto.StatusCode = (int)response.StatusCode;
                availablePlotResponse.apiResponseDto.Message = string.Empty;
            }
            else if (response.StatusCode == HttpStatusCode.InternalServerError)
            {
                availablePlotResponse.apiResponseDto = new ApiResponseDto();
                availablePlotResponse.apiResponseDto.StatusCode = (int)response.StatusCode;
                availablePlotResponse.apiResponseDto.Message = (string)response.ReasonPhrase;
            }
            else
            {
                availablePlotResponse.apiResponseDto = new ApiResponseDto();
                availablePlotResponse.apiResponseDto.StatusCode = (int)response.StatusCode;
                availablePlotResponse.apiResponseDto.Message = "Unable to plot in this area";
            }
            return availablePlotResponse;
        }
        public async Task<int> RemoveDriverPlot(Guid driverID, string accessToken)
        {
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{driverID}/driver-leave-plot");
            Console.WriteLine($"URI: {uri}");
            string json = JsonSerializer.Serialize(new { });
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            return (int)response.StatusCode;
        }
        public async Task<StartTripResponse> StartTripFutureBooking(StartTripRequest startTripRequest, string accessToken, string bookingId)
        {
            StartTripResponse startTripResponse = new StartTripResponse();
            Uri uri = new Uri($"{BASE_URL_RYDO_API}/v1/bookings/{bookingId}/head-to-pickup");
            Console.WriteLine($"URI: {uri}");

            string json = JsonSerializer.Serialize(startTripRequest);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            HttpResponseMessage response = await _httpClient.PutAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var responseData = await response.Content.ReadAsStringAsync();
                startTripResponse = JsonSerializer.Deserialize<StartTripResponse>(responseData, options);
            }
            startTripResponse.ResponseStatusCode = (int)response.StatusCode;
            startTripResponse.Message = (string)response.ReasonPhrase;
            return startTripResponse;
        }
        public async Task<bool> DriverAppSelectedPermissions(string appToken, DriverAppSelectedPermissionsDto request)
        {
            Uri uri = new Uri($"{BASE_URL}/DriverAssistantApp/DriverAppSelectedPermissions?token={appToken}");
            string json = JsonSerializer.Serialize(request);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
            HttpClient _httpClient = new HttpClient();
            PutAppVersionInHeader(_httpClient);
            var response = await _httpClient.PutAsync(uri, content);

            return response.IsSuccessStatusCode;
        }

        #endregion

        #region Utility

        private void PutAppVersionInHeader(HttpClient _httpClient)
        {
            string[] parts = AppInfo.Version.ToString().Split('.');
            string formattedString = parts.Select(p => int.Parse(p).ToString("D2")).Aggregate((p1, p2) => p1 + p2);

            _httpClient.DefaultRequestHeaders.Add("app-version", formattedString);
        }

        #endregion Utility
    }
}