namespace Hims.Domain.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Hims.Shared.UserModels.ChargeManagement;
    using Shared.EntityModels;
    using Shared.UserModels;
    using Shared.UserModels.Filters;
    using Shared.UserModels.Common;
    using Hims.Domain.Entities;

    /// <summary>
    /// The PatientService interface.
    /// </summary>
    public interface IPatientService
    {
        /// <summary>
        /// The register async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> RegisterAsync(PatientRegistrationModel model);

        /// <summary>
        /// The find async.
        /// </summary>
        /// <param name="patientId">
        /// The patient id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<PatientModel> FindAsync(int patientId);

        Task<Patient> GetRawAsync(int patientId);

        /// <summary>
        /// The fetch async.
        /// </summary>
        /// <param name="model">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<PatientModel>> FetchExistingPatientsAsync(PatientModel model);
        /// <summary>
        /// The fetch async.
        /// </summary>
        /// <param name="patientId">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<PatientFamilyModel>> FetchPatientFamilyAsync(int patientId);
        /// <summary>
        /// The fetch async.
        /// </summary>
        /// <param name="patientId">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> FetchPatientFamilyIdAsync(int patientId);
        /// <summary>
        /// The check follow up days async.
        /// </summary>
        /// <param name="model">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<AppointmentModel> CheckForFollowUpForPatientAsync(AppointmentModel model);

        /// <summary>
        /// The find async.
        /// </summary>
        /// <param name="guid">
        /// The patient guid.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<PatientModel> FindAsync(Guid guid);

        /// <summary>
        /// The fetch async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<PatientModel>> FetchAsync(PatientFilterModel model);

        /// <summary>
        /// The add async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="patientEmergencies">
        /// The patient Emergencies.
        /// </param>
        /// <param name="patientInsurances">
        /// The patient Insurances.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<Tuple<int, int, Guid?>> AddAsync(PatientModel model, List<PatientEmergencyModel> patientEmergencies, List<PatientInsuranceModel> patientInsurances, PatientFamilyModel pfModel, List<PatientFamilyModel> patientFamilyModel);
        // Task<Tuple<int, int, Guid?>> AddAsync(PatientModel model, List<PatientEmergencyModel> patientEmergencies, List<PatientInsuranceModel> patientInsurances);
        Task<Tuple<int, int, Guid?>> AddBabyPatientAsync(PatientModel model, List<PatientEmergencyModel> patientEmergencies, List<PatientInsuranceModel> patientInsurances, PatientFamilyModel pfModel, List<PatientFamilyModel> patientFamilyModel);

        /// <summary>
        /// The add patient async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// // The add patient async.
        /// </summary>
        /// <param name="pfModel">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<Tuple<int, Guid?>> AddPatientAsync(PatientModel model, PatientFamilyModel pfModel);

        /// <summary>
        /// Adds the unidentified patient asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        Task<Tuple<int, Guid?>> AddUnidentifiedPatientAsync(PatientModel model);

        /// <summary>
        /// The update async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="patientEmergencies">
        /// The patient Emergencies.
        /// </param>
        /// <param name="patientInsurances">
        /// The patient Insurances.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdateAsync(PatientModel model, List<PatientEmergencyModel> patientEmergencies, List<PatientInsuranceModel> patientInsurances, PatientFamilyModel pfModel, List<PatientFamilyModel> patientFamilyModel);

        /// <summary>
        /// The update async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdatePatientDetailsAsync(PatientModel model, PatientFamilyModel pfModel);
        /// <summary>
        /// The edit async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> EditAsync(EditPatientModel model);

        /// <summary>
        /// The update image urls async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="guid">
        /// the guid.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdateImageUrlsAsync(PatientModel model, Guid guid);

        /// <summary>
        /// The check patient async.
        /// </summary>
        /// <param name="mobile">
        /// The mobile.
        /// </param>
        /// <param name="countryId">
        /// The country Id.
        /// </param>
        /// <param name="email">
        /// The email.
        /// </param>
        /// <param name="patientId">
        /// The patient id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> CheckPatientAsync(string mobile, int? countryId, string email, int patientId);


        /// <summary>
        /// The modify status async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> ModifyStatusAsync(PatientModel model);

        /// <summary>
        /// The locked status async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> LockedStatusAsync(PatientModel model);

        /// <summary>
        /// The add family member.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> AddFamilyMember(PatientFamilyModel model);

        /// <summary>
        /// The fetch family members.
        /// </summary>
        /// <param name="patientId">
        /// The patient id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<PatientFamilyModel>> FetchFamilyMembers(int patientId);

        /// <summary>
        /// The update family members.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdateFamilyMembers(PatientFamilyModel model);

        /// <summary>
        /// The delete family member.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> DeleteFamilyMember(PatientFamilyModel model);

        /// <summary>
        /// The register async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> RegisterWithOutOtpAsync(PatientRegistrationModel model);

        /// <summary>
        /// The modify status async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> ManualVerifyAsync(PatientModel model);

        /// <summary>
        /// The get referral code async.
        /// </summary>
        /// <param name="patientId">
        /// The patient Id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<string> GetReferralCodeAsync(int patientId);

        /// <summary>
        /// The get referral code async.
        /// </summary>
        /// <param name="referralCode">
        /// The patient Id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<bool> VerifyReferralCodeAsync(string referralCode);

        /// <summary>
        /// The get referral code async.
        /// </summary>
        /// <param name="referralCode">
        /// The patient Id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> GetReferralByAsync(string referralCode);


        /// <summary>
        /// The get provider availability async.
        /// </summary>
        /// <param name="providerId">
        /// The provider id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<InsertModel> FindPatientByPatientId(int providerId);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="admissionId"></param>
        /// <returns></returns>
        Task<string> FindPatientByAdmissionId(int admissionId);

        /// <summary>
        /// The check follow up days for ip async.
        /// </summary>
        /// <param name="model">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<AdmissionModel> CheckForFollowUpForInPatientAsync(AdmissionModel model);

        /// <summary>
        /// Updates the discharg date asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        Task<int> UpdateDischargDateAsync(UpdateExpectedDischargeDateModel model);

        /// <summary>
        /// Gets the department identifier by admission identifier.
        /// </summary>
        /// <param name="admissionId">The admission identifier.</param>
        /// <returns></returns>
        Task<int> GetDepartmentIdByAdmissionId(int admissionId);

        /// <summary>
        /// Fetches the patients asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        Task<IEnumerable<PatientModel>> FetchPatientsAsync(PatientModel model);

        /// <summary>
        /// Modifies the patient registration charge.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        Task<int> ModifyPatientRegistrationCharge(PatientRegistrationChargeModel model);

        /// <summary>
        /// Fetches the registration charges asynchronous.
        /// </summary>
        /// <param name="locationId">The location identifier.</param>
        /// <returns></returns>
        Task<IEnumerable<PatientRegistrationChargeModel>> FetchRegistrationChargesAsync(int locationId);

        /// <summary>
        /// Applies the registration asynchronous.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <param name="locationId"></param>
        /// <returns></returns>
        Task<int> ApplyRegistrationAsync(int id, int locationId);

        /// <summary>
        /// Fetches the patient registration bill asynchronous.
        /// </summary>
        /// <param name="patientId">The patient identifier.</param>
        /// <returns></returns>
        Task<RegistrationBillModel> FetchPatientRegistrationBillAsync(int patientId);

        /// <summary>
        /// Fetches the patient registration bill for relative patient.
        /// </summary>
        /// <param name="patientId">The patient identifier.</param>
        /// <returns></returns>
        Task<IEnumerable<RegistrationBillModel>> FetchPatientRegistrationBillForRelativePatient(int patientId);

        /// <summary>
        /// The fetch registration charges.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<string> FetchPatientRegistrationCharges(int locationId);

        /// <summary>
        /// To fetch profile Image from FTP.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        //Task<string> FetchPatientImageThumbnailBase64(int patientId, string url);
        ///// <summary>
        ///// To fetch profile Image from FTP.
        ///// </summary>
        ///// <param name="id">The identifier.</param>
        ///// <param name="url">The profile image or thumbnail url.</param>
        ///// <returns>
        ///// The <see cref="Task"/>.
        ///// </returns>
        //Task<string> FetchImageThumbnailBase64(int id, string url);


        /// <summary>
        /// Fetches the patients asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        Task<IEnumerable<PatientModel>> FetchPatientListAsync(PatientListModel model);

        /// <summary>
        /// The get referral code async.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<string> GetLatestUMRNo();

        /// <summary>
        /// Fetches the patients asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        Task<IEnumerable<PatientModel>> FetchAppointmentSchedulePatientsAsync(PatientModel model);
        /// <summary>
        /// Fetches the patients asynchronous.
        /// </summary>
        /// <param name="patientId">The model.</param>
        /// <returns></returns>
        Task<IEnumerable<ANCCardGenerationModel>> FetchANCCard(int patientId);

        Task<PatientTimeLineModel> FetchPatientTimeLine(int? patientId);
    }
}
