using GMCabsDriverAssistant.Enums;
using GMCabsDriverAssistant.Models;
using GMCabsDriverAssistant.Services;
using GMCabsDriverAssistantSolution.Models.Rydo;
using GMCabsDriverAssistantSolution.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace GMCabsDriverAssistantSolution.ViewModels
{
    [QueryProperty(nameof(BookingJson), nameof(BookingJson))]
    public class BookingDetailViewModel : BaseViewModel
    {
        #region Constants
        private const int RYDO_METER_FARE_PROVIDER_CHARGE = 10;
        private const int RYDO_FIXED_PRICE_PROVIDER_CHARGE = 10;
        private const int RYDO_METER_FARE_PROVIDER_CHARGE_GM_DRIVER = 10;
        private const int RYDO_FIXED_PRICE_PROVIDER_CHARGE_GM_DRIVER = 5;
        #endregion

        #region Fields
        private string _bookingId;

        private float distance;

        private string formattedDistance;

        private string startAddress;

        private string startSuburb;

        private string endAddress;

        private string endSuburb;

        private string rewardPoints;

        private double bookingFee;

        private bool isCorporateBooking;

        private string fareTypeValue;

        private int? fixedAmount;

        private bool isFutureBooking;

        private int pickUpTime;

        private string formattedPickUpTime;
        private string formattedPickUpTimeDateOnly;
        private string formattedPickUpTimeTimeOnly;
        private string bookingJson;

        private string startStreetName;
        private string endStreetName;


        #endregion

        #region Properties
        public Guid Id { get; set; }

        public string BookingId
        {
            get => _bookingId;
            set
            {
                _bookingId = value;
                // LoadBooking(Guid.Parse(value));
            }
        }

        public float Distance
        {
            get => distance;
            set => SetProperty(ref distance, value);
        }

        public string FormattedDistance
        {
            get => (distance >= 1000) ? $"{distance / 1000:0.##}k" : $"{(int)distance}m";
            set => SetProperty(ref formattedDistance, value);
        }

        public string StartAddress
        {
            get => startAddress;
            set => SetProperty(ref startAddress, value);
        }

        public string StartSuburb
        {
            get => startSuburb;
            set => SetProperty(ref startSuburb, value);
        }

        public string EndAddress
        {
            get => endAddress;
            set => SetProperty(ref endAddress, value);
        }

        public string EndSuburb
        {
            get => endSuburb;
            set => SetProperty(ref endSuburb, value);
        }

        public string RewardPoints
        {
            get => rewardPoints;
            set => SetProperty(ref rewardPoints, value);
        }

        public double BookingFee
        {
            get => bookingFee;
            set => SetProperty(ref bookingFee, value);
        }

        public bool IsCorporateBooking
        {
            get => isCorporateBooking;
            set => SetProperty(ref isCorporateBooking, value);
        }

        public string FareTypeValue
        {
            get => fareTypeValue;
            set => SetProperty(ref fareTypeValue, value);
        }

        public int? FixedAmount
        {
            get => fixedAmount;
            set => SetProperty(ref fixedAmount, value);
        }
        public bool IsFutureBooking
        {
            get => isFutureBooking;
            set => SetProperty(ref isFutureBooking, value);
        }

        public int PickUpTime
        {
            get => pickUpTime;
            set => SetProperty(ref pickUpTime, value);
        }
        public string FormattedPickUpTime
        {
            get
            {
                DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
                dateTime = dateTime.AddSeconds(pickUpTime).ToLocalTime();
                return dateTime.ToString("dd/MM/yyyy hh:mm tt");
            }
            set => SetProperty(ref formattedPickUpTime, value);
        }

        public Command OnAcceptBookingClicked { get; }

        public Command OnDeclineBookingClicked { get; }

        public string BookingJson
        {
            get => bookingJson;
            set
            {
                bookingJson = value;
                LoadBooking(value);
            }
        }

        public string StartStreetName
        {
            get => startStreetName;
            set => SetProperty(ref startStreetName, value);
        }

        public string EndStreetName
        {
            get => endStreetName;
            set => SetProperty(ref endStreetName, value);
        }


        #endregion

        #region Constructor
        public BookingDetailViewModel()
        {
            Title = "Booking Details";
            OnAcceptBookingClicked = new Command(async () => { await AcceptBooking(); });
            OnDeclineBookingClicked = new Command(async () => { await DeclineBooking(Id.ToString()); });
        }
        public BookingDetailViewModel(Guid bookingId)
        {
            BookingId = bookingId.ToString();
            Title = "Booking Details";
            OnAcceptBookingClicked = new Command(async () => { await AcceptBooking(); });
            OnDeclineBookingClicked = new Command(async () => { await DeclineBooking(Id.ToString()); });
        }
        #endregion

        #region Method
        private async void LoadBooking(string bookingJson)
        {
            /* string rydoAccessToken = Preferences.Get(EftposLoginResponse.RYDO_ACCESS_TOKEN,"");
             GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
             var booking = await gmCabsDriverService.GetBookingDetails(rydoAccessToken, bookingId);*/
            BookingDto booking = JsonSerializer.Deserialize<BookingDto>(bookingJson);
            if (booking.BookingId == Guid.Empty)
            {
                await Shell.Current.GoToAsync("..");
            }

            Id = booking.BookingId;
            Distance = booking.Distance;
            FormattedDistance = booking.Distance.ToString();
            StartAddress = booking.StartAddress;
            StartSuburb = booking.StartSuburb;
            EndAddress = booking.EndAddress;
            EndSuburb = booking.EndSuburb;
            IsCorporateBooking = booking.IsCorporate;
            FixedAmount = booking.FixedAmount;
            IsFutureBooking = booking.FutureBooking;
            PickUpTime = booking.PickupTime;
            FormattedPickUpTime = booking.PickupTime.ToString();
            BookingFee = 0;

            if (FixedAmount != null)
            {
                decimal amount = (decimal)(FixedAmount / 100.0);
                FareTypeValue = "$" + amount;
            }
            else
            {
                FareTypeValue = "METER";
            }
            RewardPoints = booking.RydoStars > 0 ? string.Format($"+{booking.RydoStars}") : booking.RydoStars.ToString();
            var preferredDriver = booking.PriorityDriver;
            if (preferredDriver)
            {
                if (booking.FareType == FareType.Fixed)
                {
                    if (booking.FixedAmount > booking.MinFareAmount)
                    {
                        BookingFee = booking.ProviderChargeFixedFarePreferred.Value;
                    }
                }
                else if (booking.FareType == FareType.Meter)
                {
                    BookingFee = booking.ProviderChargeMeterFarePreferred.Value;
                }
            }
            else
            {
                if (booking.FareType == FareType.Fixed)
                {
                    if (booking.FixedAmount > booking.MinFareAmount)
                    {
                        BookingFee = booking.ProviderChargeFixedFare.Value;
                    }
                }
                else if (booking.FareType == FareType.Meter)
                {
                    BookingFee = booking.ProviderChargeMeterFare.Value;
                }
            }

            string[] splitStartAddresses = StartAddress.Split(' ');
            bool isStartAddressNumberOccurance = splitStartAddresses[0].Any(letter => char.IsDigit(letter));

            string[] splitEndAddresses = EndAddress.Split(' ');
            bool isEndAddressNumberOccurance = splitEndAddresses[0].Any(letter => char.IsDigit(letter));

            if (isEndAddressNumberOccurance)
            {
                StartStreetName = StartAddress.Substring(StartAddress.IndexOf(' ') + 1);
                StartStreetName = StartStreetName + $", {StartSuburb}";
            }
            else
            {
                StartStreetName = StartSuburb;
            }

            if (isEndAddressNumberOccurance)
            {
                EndStreetName = EndAddress.Substring(EndAddress.IndexOf(' ') + 1);
                EndStreetName = EndStreetName + $", {EndSuburb}";
            }
            else
            {
                EndStreetName = EndSuburb;
            }
        }

        [Obsolete]
        private async Task AcceptBooking()
        {
            await Shell.Current.GoToAsync($"{nameof(AcceptBookingPage)}?{nameof(AcceptBookingViewModel.BookingId)}={Id}&{nameof(AcceptBookingViewModel.PickUpAddress)}={StartAddress}&{nameof(AcceptBookingViewModel.DropUpAddress)}={EndAddress}&{nameof(AcceptBookingViewModel.IsFutureBooking)}={IsFutureBooking}");
        }

        private async Task DeclineBooking(string booking_Id)
        {
            string rydoAccessToken = Preferences.Get(EftposLoginResponse.RYDO_ACCESS_TOKEN, "");
            Guid driverId = Guid.Parse(Preferences.Get(LoginResponseDto.USER_CODE, ""));
            GMCabsDriverService gmCabsDriverService = new GMCabsDriverService();
            AcceptDeclineBookingRequest acceptBookingRequest = new AcceptDeclineBookingRequest();
            acceptBookingRequest.DriverId = driverId;

            var res = await gmCabsDriverService.DeclineBooking(acceptBookingRequest, rydoAccessToken, booking_Id);
            if (res.StatusCode == 200)
            {
                await Shell.Current.GoToAsync($"//{nameof(HomePage)}");
            }
        }

        #endregion
    }
}
