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

namespace LSFE.MobApp.ViewModels.Coverage
{
    public class MarketProductVM : BaseDoctorVM
    {
        #region Service and Helper
        private readonly IFileDownloadService _fileDownloadService;
        #endregion

        #region Repository
        private readonly Repository<ProductTransaction> _productTransRepository;
        private readonly Repository<InventoryTransaction> _inventoryTransRepository;
        private readonly Repository<MRRawPlan> _mrRawPlanRepository;
        #endregion

        public ObservableCollection<ProductMaterial> Materials { get; set; }
        public ObservableCollection<SamplingItem> Samplings { get; set; }
        private readonly Doctor _doctor;
        public MarketProductVM(Doctor doctor, Repository<Doctor> doctorRepository, 
            IFileDownloadService fileDownloadService,
              Repository<ProductTransaction> productTransRepository, 
              Repository<InventoryTransaction> inventoryTransRepository,
              Repository<MRRawPlan> mrRawPlanRepository,

            ISyncService syncService, IConfiguration configuration, AddressService addressService)
             : base(doctorRepository, syncService, addressService, configuration)
        {
            _doctor = doctor;
            _fileDownloadService = fileDownloadService;
            _productTransRepository = productTransRepository;
            _inventoryTransRepository = inventoryTransRepository;
            _mrRawPlanRepository = mrRawPlanRepository;

            Materials = new ObservableCollection<ProductMaterial>();
            Samplings = new ObservableCollection<SamplingItem>();

            CloseCommand = new Command(async () => await Close());
            CopyEmailCommand = new Command(async () => await CopyEmail());
            CallPhoneCommand = new Command(async () => await CallPhone());
            DownloadMaterialCommand = new Command<ProductMaterial>(async (material) => await DownloadMaterial(material));
            OpenMaterialCommand = new Command<ProductMaterial>(async (material) => await OpenMaterial(material));
            DownloadAllCommand = new Command(async () => await DownloadAllMaterials());
            CheckAllMaterialsCommand = new Command(CheckAllMaterials);
            CheckAllSamplingCommand = new Command(CheckAllSampling);
            DoctorSignInCommand = new Command(async () => await ProcessDoctorSignIn());

            _ = LoadMaterials();
            _ = LoadSamplings();
        }
        #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));
                }
            }
        }
        private bool _isLoading;
        public bool IsLoading
        {
            get => _isLoading;
            set
            {
                _isLoading = value;
                OnPropertyChanged();
            }
        }
        #region Dr 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

        #region Styles
        public static string GetIconEmoji(int iconEmojiId)
        {
            return iconEmojiId switch
            {
                1 => "💊",
                2 => "🍎",
                3 => "🍌",
                4 => "🍓",
                5 => "🍌",
                6 => "💉",
                _ => "🧪"
            };
        }
        #endregion

        #region Command
        public ICommand CloseCommand { get; }
        public ICommand CopyEmailCommand { get; }
        public ICommand CallPhoneCommand { get; }
        public ICommand DownloadMaterialCommand { get; }
        public ICommand OpenMaterialCommand { get; }
        public ICommand DownloadAllCommand { get; }
        public ICommand CheckAllMaterialsCommand { get; }
        public ICommand CheckAllSamplingCommand { get; }
        public ICommand DoctorSignInCommand { get; }
        #endregion

        #region Method
        private async Task ProcessDoctorSignIn()
        {
            try
            {
                IsLoading = true;

                if (_doctor.Status == 2)
                {
                    await UtilityVM.ShowAlert(
                     "Warning:",
                     $"Failed to process the signature. The visitation for Dr. {_doctor.FirstName} {_doctor.LastName} has already been completed."
                 );
                    return;
                }
                  
                // Get all checked materials
                var checkedMaterials = Materials.Where(m => m.IsChecked).ToList();

                // Get all checked sampling items
                var checkedSamplings = Samplings.Where(s => s.IsChecked).ToList();

                if (!checkedMaterials.Any() && !checkedSamplings.Any())
                {
                    await Application.Current.MainPage.DisplayAlert(
                        "No Selection",
                        "Please select at least one material or sampling item.",
                        "OK");
                    return;
                }

                // Build summary message
                var vm = new ConfirmSelectionVM(
                FullName,
                Specialization,
                checkedMaterials,
                checkedSamplings,
                async () =>
                {
                    var signatureVM = new DoctorSignatureVM(
                        _doctor,
                        _addressService,
                        _syncService,
                        _mrRawPlanRepository,
                        _doctorRepository,
                        _configuration,
                        checkedMaterials,
                        checkedSamplings,
                        OnSignatureCompleted
                    );
                    var signaturePage = new DoctorSignaturePage(signatureVM);
                    await Application.Current.MainPage.Navigation.PushAsync(signaturePage);
                });

                await Application.Current.MainPage.Navigation.PushModalAsync(
                    new ConfirmSelectionModal(vm)
                );

            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to process: {ex.Message}", "OK");
            }
            finally
            {
                IsLoading = false;
            }
        }
        private async Task LoadSamplings()
        {
            try
            {
                Samplings.Clear();

                var sampleData = await _inventoryTransRepository.GetAllAsync();
                var today = DateTime.Today;
                var filtered = sampleData.Where(i => i.DoctorId == _doctor.DoctorId &&
                                i.AppointmentDate >= today &&
                                i.AppointmentDate < today.AddDays(1));

                foreach (var item in filtered)
                {
                    Samplings.Add(new SamplingItem
                    {
                        InventoryTransId = item.InventoryTransId,
                        Description = item.Description,
                        Qty = item.QtyIn,
                        IconEmoji = GetIconEmoji(item.IconEmojiId),
                        IsChecked = false
                    });
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Failed to load samplings: {ex.Message}");
            }
        }
        private async Task DownloadMaterial(ProductMaterial material)
        {
            if (material == null || material.IsDownloading) return;

            try
            {
                material.IsDownloading = true;

                await _fileDownloadService.DownloadFileAsync(material.FileUrl, material.ProductLink, CancellationToken.None);

                material.IsDownloaded = true;
                material.IsDownloading = false;

                await Application.Current.MainPage.DisplayAlert("Success", $"{material.ProductName} downloaded successfully!", "OK");
            }
            catch (Exception ex)
            {
                material.IsDownloading = false;
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to download: {ex.Message}", "OK");
            }
        }
        private async Task OpenMaterial(ProductMaterial material)
        {
            try
            {
                if (!material.IsDownloaded)
                {
                    var download = await Application.Current.MainPage.DisplayAlert(
                        "Not Downloaded",
                        "This material needs to be downloaded first. Download now?",
                        "Yes", "No");

                    if (download)
                    {
                        await DownloadMaterial(material);
                    }
                    return;
                }

                var localPath = _fileDownloadService.GetLocalFilePath(material.ProductLink);

                if (File.Exists(localPath))
                {
                    await Launcher.OpenAsync(new OpenFileRequest
                    {
                        File = new ReadOnlyFile(localPath)
                    });
                }
                else
                {
                    await Application.Current.MainPage.DisplayAlert("Error", "File not found. Please re-download.", "OK");
                    material.IsDownloaded = false;
                }
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to open file: {ex.Message}", "OK");
            }
        }
        private async Task DownloadMaterials(ProductMaterial material)
        {
            if (material == null || material.IsDownloading) return;

            try
            {
                material.IsDownloading = true;

                await _fileDownloadService.DownloadFileAsync(material.FileUrl, material.ProductLink, CancellationToken.None);

                material.IsDownloaded = true;
                material.IsDownloading = false;
            }
            catch (Exception ex)
            {
                material.IsDownloading = false;
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to download: {ex.Message}", "OK");
            }
        }
        private async Task DownloadAllMaterials()
        {
            try
            {
                await LoadMaterials();

                var allTransactions = await _productTransRepository.GetAllAsync();

                foreach (var product in allTransactions)
                {
                    var endpoint = _configuration["ApiSettings:Endpoints:GetProductFiles"];
                    var fileUrl = $"{endpoint}{Uri.EscapeDataString(product.ProductLink)}";

                    var material = new ProductMaterial
                    {
                        ProductTransId = product.ProductTransId,
                        ProductId = product.ProductId,
                        ProductName = product.ProductName,
                        ProductLink = product.ProductLink,
                        FileUrl = fileUrl,
                        FileExtension = Path.GetExtension(product.ProductLink)
                    };

                    if (!await _fileDownloadService.IsFileDownloadedAsync(product.ProductLink))
                    {
                        await DownloadMaterials(material);
                    }
                }

                await Application.Current.MainPage.DisplayAlert("Success", "All materials downloaded!", "OK");
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to download all: {ex.Message}", "OK");
            }
        }
        private async Task LoadMaterials()
        {
            IsLoading = true;

            try
            {
                await TrySyncAsync();

                Materials.Clear();

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

                var transactions = await _productTransRepository.GetAllAsync();

                var displayList = transactions
                    .Where(p => p.DoctorId == _doctor.DoctorId && p.MRRawPlanId < _doctor.MRRawPlanId)
                    .ToList();

                // Load materials in parallel
                var materialTasks = displayList.Select(async product =>
                {
                    var fileExtension = Path.GetExtension(product.ProductLink);
                    var endpoint = _configuration["ApiSettings:Endpoints:GetProductFiles"];
                    var fileUrl = $"{endpoint}{Uri.EscapeDataString(product.ProductLink)}";
                    var isDownloaded = await _fileDownloadService.IsFileDownloadedAsync(product.ProductLink);

                    return new ProductMaterial
                    {
                        ProductTransId = product.ProductTransId,
                        ProductId = product.ProductId,
                        ProductName = product.ProductName,
                        ProductLink = product.ProductLink,
                        FileUrl = fileUrl,
                        FileExtension = fileExtension,
                        IsDownloaded = isDownloaded,
                        IsChecked = false
                    };
                });

                var materials = await Task.WhenAll(materialTasks);
                foreach (var m in materials)
                    Materials.Add(m);
            }
            finally
            {
                IsLoading = false;
            }
        }
        private async Task TrySyncAsync()
        {
            try
            {
                await _syncService.SyncPullProductsAsync();
                await _syncService.SyncPullSamplesAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Sync failed: {ex.Message}");
            }
        }
        private void CheckAllMaterials()
        {
            bool allChecked = Materials.All(m => m.IsChecked);
            foreach (var material in Materials)
            {
                material.IsChecked = !allChecked;
            }
        }
        private void CheckAllSampling()
        {
            bool allChecked = Samplings.All(s => s.IsChecked);
            foreach (var sampling in Samplings)
            {
                sampling.IsChecked = !allChecked;
            }
        }
        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");
                }
            }
        }
        private void OnSignatureCompleted(byte[] signatureBytes, string signatureFilePath)
        {
            // Handle the completed signature here
            // You can save to database, upload to server, etc.

            // Example: Save the transaction record
            // var transaction = new DoctorTransaction
            // {
            //     DoctorId = _doctor.DoctorId,
            //     SignatureFilePath = signatureFilePath,
            //     TransactionDate = DateTime.Now,
            //     Materials = checkedMaterials,
            //     Samplings = checkedSamplings
            // };
            // await _repository.SaveAsync(transaction);
        }
        #endregion
    }
}