using LSFE.MobApp.Contracts;
using LSFE.MobApp.Entities.Doctor;
using LSFE.MobApp.Entities.Planning;
using LSFE.MobApp.Helpers;
using LSFE.MobApp.Pages.CoveragePlan;
using LSFE.MobApp.Services;
using LSFE.MobApp.Services.Coverage;
using LSFE.MobApp.ViewModels.Common;
using Microsoft.Extensions.Configuration;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace LSFE.MobApp.ViewModels.Coverage
{
    public class ActualCoverageVM : BaseDoctorVM
    {
        private readonly Doctor _doctor;
        private bool _isLoading;
        private ObservableCollection<DoctorVM> _doctors;
        private readonly Repository<MRRawPlan> _mrRawPlanRepository;
        public ActualCoverageVM(
            Doctor doctor,
            Repository<Doctor> doctorRepository,
            Repository<MRRawPlan> mrRawPlanrepository,
            ISyncService syncService,
            AddressService addressService,
            IConfiguration configuration)
            : base(doctorRepository, syncService, addressService, configuration)
        {
            _doctor = doctor;
            _mrRawPlanRepository = mrRawPlanrepository;

            CloseCommand = new Command(async () => await Close());
            CopyEmailCommand = new Command(async () => await CopyEmail());
            CallPhoneCommand = new Command(async () => await CallPhone());
            StartCoverageCommand = new Command(async () => await StartCoverage());
        }

        #region Status Properties - Using Helper (DRY!)
        public string StatusText => DoctorStatusHelper.GetStatusText(_doctor.Status);
        public Color StatusBackgroundColor => DoctorStatusHelper.GetStatusBackgroundColor(_doctor.Status);
        public Color StatusTextColor => DoctorStatusHelper.GetStatusTextColor(_doctor.Status);
        #endregion

        /// <summary>
        /// This method is automatically called when status updates are broadcast
        /// </summary>
        protected override async void OnDoctorStatusUpdated(int doctorId)
        {
            // Only update if it's this doctor
            if (_doctor.DoctorId == doctorId)
            {
                var updated = await RefreshDoctorFromRepositoryAsync(doctorId);
                if (updated != null)
                {
                    _doctor.Status = updated.Status;

                    // Notify UI to refresh
                    OnPropertyChanged(nameof(StatusText));
                    OnPropertyChanged(nameof(StatusBackgroundColor));
                    OnPropertyChanged(nameof(StatusTextColor));
                }
            }
        }

        public ObservableCollection<DoctorVM> Doctors
        {
            get => _doctors;
            set
            {
                _doctors = value;
                OnPropertyChanged();
            }
        }

        #region Details information
        public string FullName => $"Dr. {_doctor.FirstName} {_doctor.MiddleInitial} {_doctor.LastName}".Replace("  ", " ").Trim();
        public string EmailAddress => _doctor.EmailAddress ?? "N/A";
        public string PhoneNo => _doctor.PhoneNo ?? "N/A";
        public string LicenseNo => _doctor.LicenseNo ?? "N/A";
        public string Specialization => _doctor.SpecializationName ?? "General Practice";
        public string InstitutionName => _doctor.InstitutionName ?? "No Institution Assigned";
        public string Address => _doctor.Address ?? "No address provided";
        public string MaxVisit => $"{_doctor.MaxVisit} doctors";
        public string BirthDateFormatted => _doctor.BirthDate.ToString("MMMM dd, yyyy");
        public string CreatedDateFormatted => _doctor.CreatedDate.ToString("MMMM dd, yyyy");

        public bool HasInstitution => !string.IsNullOrEmpty(_doctor.InstitutionName);
        public bool HasAddress => !string.IsNullOrEmpty(_doctor.Address);
        #endregion

        public bool IsLoading
        {
            get => _isLoading;
            set
            {
                _isLoading = value;
                OnPropertyChanged();
            }
        }

        #region Commands
        public ICommand StartCoverageCommand { get; }
        public ICommand CloseCommand { get; }
        public ICommand CopyEmailCommand { get; }
        public ICommand CallPhoneCommand { get; }
        #endregion

        private async Task StartCoverage()
        {
            try
            {
                ((Command)StartCoverageCommand).ChangeCanExecute();

                if (_doctor.Status == 2)
                {
                    await UtilityVM.ShowAlert(
                        "Warning:",
                        $"Failed to start coverage. The visitation for Dr. {_doctor.FirstName} {_doctor.LastName} has already been completed."
                    );
                    return;
                }

                var confirm = await Application.Current.MainPage.DisplayAlert(
                      "Start Coverage",
                      "Do you want to begin coverage now?",
                      "Yes, Start",
                      "Cancel");

                if (!confirm)
                {
                    return;
                }
                await EnsurePlanInitializedAsync();
            }
            catch (Exception ex)
            {
                await UtilityVM.ShowAlert("Error", $"Failed to open Market Product page: {ex.Message}");
            }
            finally
            {
                IsLoading = false;
                ((Command)StartCoverageCommand).ChangeCanExecute();
            }
        }
        private async Task EnsurePlanInitializedAsync()
        {
            var today = DateTime.Today;
            var tomorrow = today.AddDays(1);

            var plan = await _mrRawPlanRepository.FirstOrDefaultAsync(
                r => r.MRRawPlanId==_doctor.MRRawPlanId && r.DoctorId == _doctor.DoctorId);

            var doctor = await _doctorRepository.FirstOrDefaultAsync(d => d.DoctorId == _doctor.DoctorId);

            if (plan == null)
            {
                await Application.Current.MainPage.DisplayAlert("Error", "No plan found for today.", "OK");
                return;
            }

            if (plan.StartTime == null)
            {
                plan.StartTime = DateTime.Now;
                plan.ActualCallDate = today;
                var result = await _mrRawPlanRepository.UpdateAsync(plan);

                doctor.Status = 1;
                await _doctorRepository.UpdateAsync(doctor);

                // Broadcast to ALL ViewModels - ONE LINE!
                DoctorStatusHelper.BroadcastStatusUpdate(_doctor.DoctorId);

                if (result <= 0)
                {
                    await Application.Current.MainPage.DisplayAlert(
                        "Failed",
                        "Actual coverage recording failed, please try again!",
                        "OK");
                    await Application.Current.MainPage.Navigation.PopAsync();
                }
            }


            var viewVm = new MarketProductVM(
             _doctor,
             _doctorRepository,
             ServiceHelper.GetService<IFileDownloadService>(),
             ServiceHelper.GetService<Repository<ProductTransaction>>(),
             ServiceHelper.GetService<Repository<InventoryTransaction>>(),
             ServiceHelper.GetService<Repository<MRRawPlan>>(),
             _syncService,
             _configuration,
             _addressService);

            var viewPage = new MarketProductPage(viewVm);

            IsLoading = true;

            await Application.Current.MainPage.Navigation.PushAsync(viewPage);
        }
        private async Task Close()
        {
            await Application.Current.MainPage.Navigation.PopAsync();
        }

        private async Task CopyEmail()
        {
            if (!string.IsNullOrEmpty(_doctor.EmailAddress))
            {
                await Clipboard.SetTextAsync(_doctor.EmailAddress);
                await Application.Current.MainPage.DisplayAlert("Copied", "Email address copied to clipboard", "OK");
            }
        }

        private async Task CallPhone()
        {
            if (!string.IsNullOrEmpty(_doctor.PhoneNo))
            {
                try
                {
                    if (PhoneDialer.Default.IsSupported)
                    {
                        PhoneDialer.Default.Open(_doctor.PhoneNo);
                    }
                    else
                    {
                        await Clipboard.SetTextAsync(_doctor.PhoneNo);
                        await Application.Current.MainPage.DisplayAlert("Phone Number", "Phone number copied to clipboard", "OK");
                    }
                }
                catch (Exception ex)
                {
                    await Application.Current.MainPage.DisplayAlert("Error", $"Unable to dial: {ex.Message}", "OK");
                }
            }
        }
    }
}