using LSFE.MobApp.Contracts;
using LSFE.MobApp.Entities.Doctor;
using LSFE.MobApp.Entities.Location;
using LSFE.MobApp.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace LSFE.MobApp.ViewModels.Coverage
{
    public class AddEditDoctorVM : INotifyPropertyChanged
    {
        private readonly IApiClient<Doctor> _doctorApiClient;
        private readonly IApiClient<Institution> _institutionApiClient;
        private readonly Doctor _existingDoctor;
        private readonly bool _isEditMode;

        private string _firstName;
        private string _middleInitial;
        private string _lastName;
        private string _specialization;
        private string _emailAddress;
        private string _phoneNo;
        private string _address;
        private string _licenseNo;
        private DateTime _birthDate = DateTime.Now.AddYears(-30);
        private string _maxVisit = "10";
        private int _selectedStatusIndex;
        private Institution _selectedInstitution;
        private bool _isLoading;

        public AddEditDoctorVM(
            IApiClient<Doctor> doctorApiClient,
            IApiClient<Institution> institutionApiClient,
            List<Institution> institutions,
            Doctor existingDoctor = null)
        {
            _doctorApiClient = doctorApiClient;
            _institutionApiClient = institutionApiClient;
            _existingDoctor = existingDoctor;
            _isEditMode = existingDoctor != null;

            Institutions = institutions;
            StatusOptions = new List<string> { "Pending", "Approved", "For DSM Approval", "Inactive" };

            if (_isEditMode)
            {
                LoadExistingDoctor();
            }

            SaveCommand = new Command(async () => await SaveDoctor(), () => !IsLoading);
            CancelCommand = new Command(async () => await Cancel());
        }

        private void LoadExistingDoctor()
        {
            FirstName = _existingDoctor.FirstName;
            MiddleInitial = _existingDoctor.MiddleInitial;
            LastName = _existingDoctor.LastName;
            Specialization = _existingDoctor.SpecializationName;
            EmailAddress = _existingDoctor.EmailAddress;
            PhoneNo = _existingDoctor.PhoneNo;
            Address = _existingDoctor.Address;
            LicenseNo = _existingDoctor.LicenseNo;
            BirthDate = _existingDoctor.BirthDate;
            MaxVisit = _existingDoctor.MaxVisit.ToString();
            SelectedStatusIndex = _existingDoctor.Status;

            if (_existingDoctor.InstitutionId > 0)
            {
                SelectedInstitution = Institutions.FirstOrDefault(i => i.InstitutionId == _existingDoctor.InstitutionId);
            }
        }

        public string PageTitle => _isEditMode ? "Edit Doctor" : "Add New Doctor";
        public string SaveButtonText => _isEditMode ? "Update Doctor" : "Create Doctor";

        public string FirstName
        {
            get => _firstName;
            set { _firstName = value; OnPropertyChanged(); }
        }

        public string MiddleInitial
        {
            get => _middleInitial;
            set { _middleInitial = value; OnPropertyChanged(); }
        }

        public string LastName
        {
            get => _lastName;
            set { _lastName = value; OnPropertyChanged(); }
        }

        public string Specialization
        {
            get => _specialization;
            set { _specialization = value; OnPropertyChanged(); }
        }

        public string EmailAddress
        {
            get => _emailAddress;
            set { _emailAddress = value; OnPropertyChanged(); }
        }

        public string PhoneNo
        {
            get => _phoneNo;
            set { _phoneNo = value; OnPropertyChanged(); }
        }

        public string Address
        {
            get => _address;
            set { _address = value; OnPropertyChanged(); }
        }

        public string LicenseNo
        {
            get => _licenseNo;
            set { _licenseNo = value; OnPropertyChanged(); }
        }

        public DateTime BirthDate
        {
            get => _birthDate;
            set { _birthDate = value; OnPropertyChanged(); }
        }

        public string MaxVisit
        {
            get => _maxVisit;
            set { _maxVisit = value; OnPropertyChanged(); }
        }

        public int SelectedStatusIndex
        {
            get => _selectedStatusIndex;
            set { _selectedStatusIndex = value; OnPropertyChanged(); }
        }

        public Institution SelectedInstitution
        {
            get => _selectedInstitution;
            set { _selectedInstitution = value; OnPropertyChanged(); }
        }

        public List<Institution> Institutions { get; }
        public List<string> StatusOptions { get; }

        public bool IsLoading
        {
            get => _isLoading;
            set
            {
                _isLoading = value;
                OnPropertyChanged();
                ((Command)SaveCommand).ChangeCanExecute();
            }
        }

        public ICommand SaveCommand { get; }
        public ICommand CancelCommand { get; }

        private async Task SaveDoctor()
        {
            // Validation
            if (string.IsNullOrWhiteSpace(FirstName))
            {
                await Application.Current.MainPage.DisplayAlert("Validation Error", "First name is required", "OK");
                return;
            }

            if (string.IsNullOrWhiteSpace(LastName))
            {
                await Application.Current.MainPage.DisplayAlert("Validation Error", "Last name is required", "OK");
                return;
            }

            if (string.IsNullOrWhiteSpace(EmailAddress))
            {
                await Application.Current.MainPage.DisplayAlert("Validation Error", "Email address is required", "OK");
                return;
            }

            if (string.IsNullOrWhiteSpace(PhoneNo))
            {
                await Application.Current.MainPage.DisplayAlert("Validation Error", "Phone number is required", "OK");
                return;
            }

            if (string.IsNullOrWhiteSpace(LicenseNo))
            {
                await Application.Current.MainPage.DisplayAlert("Validation Error", "License number is required", "OK");
                return;
            }

            if (!byte.TryParse(MaxVisit, out byte maxVisitValue))
            {
                await Application.Current.MainPage.DisplayAlert("Validation Error", "Max visits must be a valid number", "OK");
                return;
            }

            try
            {
                IsLoading = true;

                Doctor doctor;
                if (_isEditMode)
                {
                    doctor = _existingDoctor;
                }
                else
                {
                    doctor = new Doctor
                    {
                        Id = Guid.NewGuid(),
                        CreatedDate = DateTime.Now
                    };
                }

                // Map properties
                doctor.FirstName = FirstName?.Trim();
                doctor.MiddleInitial = MiddleInitial?.Trim();
                doctor.LastName = LastName?.Trim();
                doctor.SpecializationName = Specialization?.Trim();
                doctor.EmailAddress = EmailAddress?.Trim();
                doctor.PhoneNo = PhoneNo?.Trim();
                doctor.Address = Address?.Trim();
                doctor.LicenseNo = LicenseNo?.Trim();
                doctor.BirthDate = BirthDate;
                doctor.MaxVisit = maxVisitValue;
                doctor.Status = (byte)SelectedStatusIndex;
                doctor.InstitutionId = SelectedInstitution?.InstitutionId ?? 0;
                doctor.IsActive = true;

                ApiResponse<Doctor> response;
                if (_isEditMode)
                {
                    response = await _doctorApiClient.UpdateAsync(doctor.Id,doctor);
                }
                else
                {
                    response = await _doctorApiClient.CreateAsync(doctor);
                }

                if (response.Success)
                {
                    await Application.Current.MainPage.DisplayAlert(
                        "Success",
                        _isEditMode ? "Doctor updated successfully" : "Doctor created successfully",
                        "OK");

                    // Notify parent to reload
                    MessagingCenter.Send(this, "DoctorSaved");

                    await Application.Current.MainPage.Navigation.PopModalAsync();
                }
                else
                {
                    await Application.Current.MainPage.DisplayAlert(
                        "Error",
                        response.Message ?? "Failed to save doctor",
                        "OK");
                }
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("Error", $"Failed to save doctor: {ex.Message}", "OK");
            }
            finally
            {
                IsLoading = false;
            }
        }

        private async Task Cancel()
        {
            var hasChanges = !string.IsNullOrEmpty(FirstName) ||
                            !string.IsNullOrEmpty(LastName) ||
                            !string.IsNullOrEmpty(EmailAddress);

            if (hasChanges)
            {
                var confirm = await Application.Current.MainPage.DisplayAlert(
                    "Discard Changes",
                    "Are you sure you want to discard your changes?",
                    "Discard",
                    "Continue Editing");

                if (!confirm) return;
            }

            await Application.Current.MainPage.Navigation.PopModalAsync();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
