using LSFE.MobApp.Contracts;
using LSFE.MobApp.Entities.Doctor;
using LSFE.MobApp.Helpers;
using LSFE.MobApp.Models;
using LSFE.MobApp.Services;
using LSFE.MobApp.ViewModels.Common;
using Microsoft.Extensions.Configuration;
using System.Windows.Input;

namespace LSFE.MobApp.ViewModels.Coverage
{
    public class DoctorSignatureVM : BaseDoctorVM
    {
        private readonly List<ProductMaterial> _selectedMaterials;
        private readonly List<SamplingItem> _selectedSamplings;
        private Action<byte[], string> _onSignatureCompleted;
        private readonly AddressService _addressService;

        #region Repository
        private readonly Repository<Entities.Planning.MRRawPlan> _mrRawPlanRepository;
        private readonly Repository<Entities.Doctor.Doctor> _doctorRepository;
        #endregion

        private readonly Entities.Doctor.Doctor _doctor;
        public DoctorSignatureVM(Entities.Doctor.Doctor doctor,
            AddressService addressService,
            ISyncService syncService,
            Repository<Entities.Planning.MRRawPlan> mrRawPlanRepository,
            Repository<Entities.Doctor.Doctor> doctorRepository, IConfiguration configuration,

            List<ProductMaterial> selectedMaterials,
            List<SamplingItem> selectedSamplings,
            Action<byte[], string> onSignatureCompleted = null) 
            : base(doctorRepository, syncService, addressService, configuration)
        {
            _doctor=doctor;
            _mrRawPlanRepository = mrRawPlanRepository;
            _doctorRepository=doctorRepository;
            _selectedMaterials = selectedMaterials;
            _selectedSamplings = selectedSamplings;
            _onSignatureCompleted = onSignatureCompleted;
            _addressService = addressService;

            // Initialize commands
            SelectDrawTabCommand = new Command(SelectDrawTab);
            SelectPhotoTabCommand = new Command(SelectPhotoTab);
            ClearSignatureCommand = new Command(ClearSignature);
            PreviewSignatureCommand = new Command(async () => await PreviewSignature());
            TakePhotoCommand = new Command(async () => await TakePhoto());
            RemovePhotoCommand = new Command(RemovePhoto);
            ConfirmSignatureCommand = new Command(async () => await ConfirmSignature());
            CancelCommand = new Command(async () => await Cancel());

            // Default to draw tab
            IsDrawTabSelected = true;
        }
        #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
        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));
                }
            }
        }

        #region Properties

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

        private bool _isDrawTabSelected;
        public bool IsDrawTabSelected
        {
            get => _isDrawTabSelected;
            set
            {
                _isDrawTabSelected = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(IsPhotoTabSelected));
                OnPropertyChanged(nameof(DrawTabBackgroundColor));
                OnPropertyChanged(nameof(DrawTabTextColor));
                OnPropertyChanged(nameof(PhotoTabBackgroundColor));
                OnPropertyChanged(nameof(PhotoTabTextColor));
                OnPropertyChanged(nameof(ShowClearButton));
            }
        }

        public bool IsPhotoTabSelected => !_isDrawTabSelected;
        public bool ShowClearButton => _isDrawTabSelected && !IsSignaturePadEmpty;
        public Color DrawTabBackgroundColor => _isDrawTabSelected ? Color.FromArgb("#0EA5E9") : Color.FromArgb("#F3F4F6");
        public Color DrawTabTextColor => _isDrawTabSelected ? Colors.White : Color.FromArgb("#6B7280");
        public Color PhotoTabBackgroundColor => !_isDrawTabSelected ? Color.FromArgb("#0EA5E9") : Color.FromArgb("#F3F4F6");
        public Color PhotoTabTextColor => !_isDrawTabSelected ? Colors.White : Color.FromArgb("#6B7280");

        public string DoctorName => $"{_doctor.FirstName} {_doctor.MiddleInitial} {_doctor.LastName}";
        public string DoctorSpecialization => _doctor.SpecializationName;

        public string SelectedItemsSummary
        {
            get
            {
                var summary = "";
                if (_selectedMaterials?.Any() == true)
                {
                    summary += $"📄 {_selectedMaterials.Count} Marketing Material(s)\n";
                }
                if (_selectedSamplings?.Any() == true)
                {
                    summary += $"💊 {_selectedSamplings.Count} Sampling Item(s)";
                }
                return summary.Trim();
            }
        }

        private ImageSource _signaturePhotoSource;
        public ImageSource SignaturePhotoSource
        {
            get => _signaturePhotoSource;
            set
            {
                _signaturePhotoSource = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(HasSignaturePhoto));
                OnPropertyChanged(nameof(HasNoSignaturePhoto));
                OnPropertyChanged(nameof(CanConfirm));
            }
        }

        public bool HasSignaturePhoto => _signaturePhotoSource != null;
        public bool HasNoSignaturePhoto => _signaturePhotoSource == null;

        private byte[] _signaturePhotoBytes;

        private ImageSource _finalSignatureSource;
        public ImageSource FinalSignatureSource
        {
            get => _finalSignatureSource;
            set
            {
                _finalSignatureSource = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(HasFinalSignature));
            }
        }

        public bool HasFinalSignature => _finalSignatureSource != null;

        private byte[] _finalSignatureBytes;

        private string _signatureTimestamp;
        public string SignatureTimestamp
        {
            get => _signatureTimestamp;
            set
            {
                _signatureTimestamp = value;
                OnPropertyChanged();
            }
        }

        public bool CanConfirm => HasFinalSignature || HasSignaturePhoto || (_isDrawTabSelected && !IsSignaturePadEmpty);
        private bool _isSignaturePadEmpty = true;
        public bool IsSignaturePadEmpty
        {
            get => _isSignaturePadEmpty;
            set
            {
                _isSignaturePadEmpty = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(CanConfirm));
                OnPropertyChanged(nameof(ShowClearButton));
            }
        }
        #endregion

        #region Commands
        public ICommand SelectDrawTabCommand { get; }
        public ICommand SelectPhotoTabCommand { get; }
        public ICommand ClearSignatureCommand { get; set; }
        public ICommand PreviewSignatureCommand { get; set; }
        public ICommand TakePhotoCommand { get; }
        public ICommand ChoosePhotoCommand { get; }
        public ICommand RemovePhotoCommand { get; }
        public ICommand ConfirmSignatureCommand { get; }
        public ICommand CancelCommand { get; }

        #endregion

        #region Methods
        private void SelectDrawTab()
        {
            IsDrawTabSelected = true;
        }

        private void SelectPhotoTab()
        {
            IsDrawTabSelected = false;
        }

        public async Task PreviewSignature()
        {
            try
            {
                IsLoading = true;
                await Application.Current.MainPage.DisplayAlert(
                    "Preview",
                    "Signature preview will be shown here",
                    "OK");
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to preview: {ex.Message}", "OK");
            }
            finally
            {
                IsLoading = false;
            }
        }

        private bool _isPhotoSignature;

        public void SetSignatureFromPad(byte[] signatureBytes)
        {
            if (signatureBytes != null && signatureBytes.Length > 0)
            {
                _finalSignatureBytes = signatureBytes;
                FinalSignatureSource = ImageSource.FromStream(() => new MemoryStream(signatureBytes));
                SignatureTimestamp = $"Signed on {DateTime.Now:MMMM dd, yyyy hh:mm tt}";
                _isPhotoSignature = false; // This is a drawn signature
            }
        }

        private async Task ProcessPhoto(FileResult photo)
        {
            try
            {
                IsLoading = true;

                using var stream = await photo.OpenReadAsync();
                using var memoryStream = new MemoryStream();
                await stream.CopyToAsync(memoryStream);

                _signaturePhotoBytes = memoryStream.ToArray();
                SignaturePhotoSource = ImageSource.FromStream(() => new MemoryStream(_signaturePhotoBytes));

                // Set as final signature
                _finalSignatureBytes = _signaturePhotoBytes;
                FinalSignatureSource = SignaturePhotoSource;
                SignatureTimestamp = $"Captured on {DateTime.Now:MMMM dd, yyyy hh:mm tt}";
                _isPhotoSignature = true; 
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to process photo: {ex.Message}", "OK");
            }
            finally
            {
                IsLoading = false;
            }
        }
        private async Task TakePhoto()
        {
            try
            {
                if (!MediaPicker.Default.IsCaptureSupported)
                {
                    await Application.Current.MainPage.DisplayAlert(
                        "Not Supported",
                        "Camera is not supported on this device",
                        "OK");
                    return;
                }

                var photo = await MediaPicker.Default.CapturePhotoAsync();
                if (photo != null)
                {
                    await ProcessPhoto(photo);
                }
            }
            catch (PermissionException)
            {
                await Application.Current.MainPage.DisplayAlert(
                    "Permission Denied",
                    "Camera permission is required to take photos. Please enable it in settings.",
                    "OK");
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to take photo: {ex.Message}", "OK");
            }
        }

        private void RemovePhoto()
        {
            SignaturePhotoSource = null;
            _signaturePhotoBytes = null;
            FinalSignatureSource = null;
            _finalSignatureBytes = null;
            SignatureTimestamp = null;
        }

        #region Facade Actual Coverage Confirmation
        private async Task ConfirmSignature()
        {
            try
            {
                // STEP 1: Ensure signature exists
                if (!await EnsureSignatureIsValid())
                    return;

                // STEP 2: Ask user to confirm
                if (!await ConfirmSignatureSave())
                    return;

                IsLoading = true;

                // STEP 3: Save signature file
                var fileName = await SaveSignatureFile();
                if (fileName == null)
                    return;

                _onSignatureCompleted?.Invoke(_finalSignatureBytes, fileName);

                // STEP 4: Update plan
                var plan = await GetTodayPlan();
                if (plan == null)
                    return;

                var doctor = await _doctorRepository.FirstOrDefaultAsync(d => d.MRRawPlanId == _doctor.MRRawPlanId);
                if (doctor == null)
                {
                    await UtilityVM.ShowAlert("Error: ", $"Doctor not found.");
                    return;
                }

                await UpdatePlanWithSignature(plan, doctor, fileName);

                // STEP 5: Sync
                await PerformSyncAndNotify();

                // STEP 6: Navigate back        

                await Application.Current.MainPage.Navigation.PopAsync();
            }
            catch (Exception ex)
            {
                await UtilityVM.ShowAlert("Error: ",$"Failed to save signature: {ex.Message}");
            }
            finally
            {
                IsLoading = false;
            }
        }
        private async Task PerformSyncAndNotify()
        {
            bool isSynced = await _syncService.SyncPostCoverageTodayAsync(_doctor.MRRawPlanId);

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

            string message = isSynced
                ? "Actual coverage was saved and synced successfully."
                : "Saved locally. Please sync again later.";

            await Application.Current.MainPage.DisplayAlert("Success", message, "OK");
        }
        private async Task<bool> ConfirmSignatureSave()
        {
            return await Application.Current.MainPage.DisplayAlert(
                "Confirm Signature",
                "Are you sure you want to save this signature?",
                "Yes, Save",
                "No"
            );
        }
        private async Task<bool> EnsureSignatureIsValid()
        {
            if (_isDrawTabSelected && _finalSignatureBytes == null)
            {
                var bytes = await GetSignatureBytesFromPad();
                if (bytes == null || bytes.Length == 0)
                {
                    await UtilityVM.ShowAlert("Signature: ","Please draw a signature before confirming.");
                    return false;
                }

                SetSignatureFromPad(bytes);
            }

            if (_finalSignatureBytes == null || _finalSignatureBytes.Length == 0)
            {
                await UtilityVM.ShowAlert("Signature: ", "Please provide a signature before confirming.");
                return false;
            }

            return true;
        }
        private async Task<string> SaveSignatureFile()
        {
            var fileName = $"signature_{DateTime.Now:yyyyMMdd_HHmmss}.png";
            var saved = await SaveSignatureToFile(_finalSignatureBytes, fileName);

            if (string.IsNullOrWhiteSpace(saved))
            {
                await UtilityVM.ShowAlert("Saving signature: ", "Failed to save signature file.");
                return null;
            }

            return fileName;
        }
        private async Task<Entities.Planning.MRRawPlan?> GetTodayPlan()
        {
            var today = DateTime.Today;
            var tomorrow = today.AddDays(1);

            var plan = await _mrRawPlanRepository.FirstOrDefaultAsync(
                r => r.CallDate >= today &&
                     r.CallDate < tomorrow &&
                     r.DoctorId == _doctor.DoctorId);

            if (plan == null)
                await UtilityVM.ShowAlert("Actual coverage: ", "No plan found for today. Cannot save signature.");

            return plan;
        }
        private async Task UpdatePlanWithSignature(
            Entities.Planning.MRRawPlan plan,Doctor doctor, string fileName)
        {

            var (locationResult,isReadableAddress) = await _addressService.GetCurrentLocationAsync();

            if (plan.EndTime != null)
                return;

            plan.SignatureFileName = fileName;
            plan.Latitude = locationResult.Latitude.ToString();
            plan.Longitude = locationResult.Longitude.ToString();
            plan.EndTime = DateTime.Now;
            plan.Location = locationResult.Address;
            plan.IsSignature = _isPhotoSignature;
            plan.IsMissed = false;
            plan.IsReschedule = false;
            plan.Status = 2; // completed
            plan.ForAddressTranslation = isReadableAddress ? false : true;
            doctor.Status = 2; // completed

            await _mrRawPlanRepository.UpdateAsync(plan);
            await _doctorRepository.UpdateAsync(doctor);
        }
        #endregion

        private Func<Task<byte[]>> _getSignatureBytesFromPad;

        public void SetGetSignatureBytesAction(Func<Task<byte[]>> getSignatureBytesAction)
        {
            _getSignatureBytesFromPad = getSignatureBytesAction;
        }

        private async Task<byte[]> GetSignatureBytesFromPad()
        {
            if (_getSignatureBytesFromPad != null)
            {
                return await _getSignatureBytesFromPad();
            }
            return null;
        }
        public static string GetFullSignaturePath(string fileName)
        {
            return Path.Combine(FileSystem.AppDataDirectory, fileName);
        }
        private async Task<string> SaveSignatureToFile(byte[] imageBytes, string fileName)
        {
            try
            {
                // Save to app data directory (just like your photo handling)
                var localFilePath = Path.Combine(FileSystem.AppDataDirectory, fileName);
                await File.WriteAllBytesAsync(localFilePath, imageBytes);

                // Return only the filename (not the full path)
                return fileName;
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to save signature file: {ex.Message}");
            }
        }
        private async Task Cancel()
        {
            var confirm = await Application.Current.MainPage.DisplayAlert(
                "Cancel",
                "Are you sure you want to cancel? Any unsaved signature will be lost.",
                "Yes, Cancel",
                "No");

            if (confirm)
            {
                await Application.Current.MainPage.Navigation.PopAsync();
            }
        }
        private Action _clearSignaturePad;

        public void SetClearSignaturePadAction(Action clearAction)
        {
            _clearSignaturePad = clearAction;
        }
        public void ClearSignature()
        {
            // Clear the final signature
            FinalSignatureSource = null;
            _finalSignatureBytes = null;
            SignatureTimestamp = null;

            // Clear the actual signature pad if the action is set
            _clearSignaturePad?.Invoke();

            OnPropertyChanged(nameof(CanConfirm));
        }
        #endregion
    }
}