namespace Hims.Domain.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Hims.Domain.Entities;
    using Hims.Shared.UserModels;
    using Shared.EntityModels;
    using Shared.UserModels.Filters;
    /// <summary>
    /// The Appointment Service interface.
    /// </summary>
    public interface IAppointmentService
    {
        Task<int> GetLatestIdAsync(int id);

        Task<Appointment> GetRawAsync(int id);

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

        /// <summary>
        /// The fetch new async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<AppointmentNewModel>> FetchNewAsync(AppointmentFilterModel model);

        /// <summary>
        /// The fetch all async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<AppointmentModel>> FetchAllAsync(AppointmentFilterModel model);

        /// <summary>
        /// The find async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<AppointmentModel> FindAsync(int appointmentId);

        /// <summary> The find by date async.</summary>
        /// <param name="appointmentDate"> The appointment date.</param>
        /// <returns>The <see cref="Task"/>.</returns>
        Task<IEnumerable<AppointmentModel>> FindByDateAsync(string appointmentDate);

        /// <summary>
        /// Finds the appointment asynchronous.
        /// </summary>
        /// <param name="appointmentId">The appointment identifier.</param>
        /// <param name="isAdmission">if set to <c>true</c> [is admission].</param>
        /// <returns></returns>
        Task<AppointmentDashboardModel> FindAppointmentAsync(int appointmentId, bool isAdmission);

        /// <summary>
        /// Fetches the appointment symptoms asynchronous.
        /// </summary>
        /// <param name="appointmentId">The appointment identifier.</param>
        /// <param name="isAdmission">if set to <c>true</c> [is admission].</param>
        /// <returns></returns>
        Task<AppointmentSymptomModel> FetchAppointmentSymptomsAsync(int appointmentId, bool isAdmission);

        /// <summary>
        /// The find by patient async.
        /// </summary>
        /// <param name="patientId">
        /// The patient id.
        /// </param>
        /// <param name="providerId">
        /// The provider Id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<AppointmentModel>> FindByPatientAsync(int patientId, int providerId);

        /// <summary>
        /// The add async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> AddAsync(AppointmentModel model);

        /// <summary>
        /// The add async.
        /// </summary>
        /// <param name="appointmentLogId">
        /// The appointment Log Id.
        /// </param>
        /// <param name="transactionId">
        /// The transaction Id.
        /// </param>
        /// <param name="transactionDetails">
        /// The transaction Details.
        /// </param>
        /// <param name="bankReference">
        /// The bank Reference.
        /// </param>
        /// <param name="bankCode">
        /// The bank Code.
        /// </param>
        /// <param name="paymentId">
        /// The payment Id.
        /// </param>
        /// <param name="salucroStatusCode"></param>
        /// <param name="salucroTransactionId"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<Tuple<int, bool, string>> AddAsync(int appointmentLogId, string transactionId, string transactionDetails, string bankReference, string bankCode, long paymentId, int salucroStatusCode, string salucroTransactionId);

        /// <summary>
        /// The reschedule async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <param name="appointmentDate">
        /// The appointment date.
        /// </param>
        /// <param name="appointmentTime">
        /// The appointment time.
        /// </param>
        /// <param name="appointmentNotes">
        /// The appointment Notes.
        /// </param>
        /// <param name="modifiedBy">
        /// The modified by.
        /// </param>
        /// <param name="providerId">
        /// The provider id.
        /// </param>
        /// <param name="providerLocationId">
        /// The provider location id.
        /// </param>
        /// <param name="departmentId">
        /// The department id.
        /// </param>
        /// <param name="locationId"></param>
        /// <param name="tokenNumber"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> RescheduleAsync(int appointmentId, DateTime appointmentDate, TimeSpan appointmentTime, TimeSpan appointmentEndTime, string appointmentNotes, int modifiedBy, int providerId, int providerAvailabilityId, int consultationTypeId, int? departmentId, int locationId, int tokenNumber, int? specializationId);

        /// <summary>
        /// The update async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment Id.
        /// </param>
        /// <param name="modifiedBy">
        /// The modified By.
        /// </param>
        /// /// <param name="reason">
        /// The reason.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> CancelAsync(int appointmentId, int? modifiedBy, string reason);

        /// <summary>
        /// The update async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment Id.
        /// </param>
        /// <param name="modifiedBy">
        /// The modified By.
        /// </param>
        /// /// <param name="patientType">
        /// The patient type.
        /// </param>
        /// <param name="visitTypeId"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdatePatientTypeAsync(int appointmentId, int modifiedBy, char? patientType, int visitTypeId);

        /// <summary>
        /// The update async.
        /// </summary>
        /// /// <param name="model">
        /// The appointment model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdatePaymentStatusAsync(PatientPaymentModel model);

        /// <summary>
        /// Adds the symptoms asynchronous.
        /// </summary>
        /// <param name="appointmentId">The appointment identifier.</param>
        /// <param name="symptoms">The symptoms.</param>
        /// <param name="createdBy">The created by.</param>
        /// <param name="isAdmission">if set to <c>true</c> [is admission].</param>
        /// <returns></returns>
        Task<int> AddSymptomsAsync(int appointmentId, string symptoms, int createdBy, bool isAdmission);

        /// <summary>
        /// Update Relation id async.
        /// </summary>
        /// <param name="appointmentId">
        /// The patient family id.
        /// </param>
        /// <param name="patientFamilyId">
        /// The symptoms.
        /// </param>
        /// /// <param name="userId">
        /// The created by.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdateRelationIdAsync(int appointmentId, int userId, int? patientFamilyId);

        /// <summary>
        /// The get delete async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> DeleteAsync(int appointmentId);

        /// <summary>
        /// Updates the encounter type asynchronous.
        /// </summary>
        /// <param name="appointmentId">The appointment identifier.</param>
        /// <param name="encounterType">Type of the encounter.</param>
        /// <param name="isAdmission">if set to <c>true</c> [is admission].</param>
        /// <returns></returns>
        Task<int> UpdateEncounterTypeAsync(int appointmentId, int encounterType, bool isAdmission);
        /// <summary>
        /// Updates the encounter type asynchronous.
        /// </summary>
        /// <param name="appointmentId">The appointment identifier.</param>
        /// <param name="isEmergency">Type of the encounter.</param>
        /// <returns></returns>
        Task<int> UpdateEmergencyTypeAsync(int appointmentId);

        /// <summary>
        /// The fetch support log async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<AppointmentSupportLogModel>> FetchSupportLogAsync(AppointmentSupportLogModel model);

        /// <summary>
        /// The update log.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> UpdateLog(AppointmentSupportLogModel model);

        /// <summary>
        /// The assign appointment to support.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> AssignAppointmentToSupport(AppointmentSupportLogModel model);

        /// <summary>
        /// The find by appointment no async.
        /// </summary>
        /// <param name="appointmentNo">
        /// The appointment no.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<AppointmentModel> FindByAppointmentNoAsync(string appointmentNo);

        /// <summary>
        /// The find previous appointment async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<PreviousAppointmentModel> FindPreviousAppointmentAsync(int appointmentId);

        /// <summary>
        /// The fetch appointment log count.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<long> FetchAppointmentLogCount();

        /// <summary>
        /// The find previous appointment async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> FindReceiptByAppointmentId(int appointmentId);

        /// <summary>
        /// The approve async.
        /// </summary>     
        ///  /// <param name="appointmentId">
        /// The model.
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<Appointment> CheckInAsync(int appointmentId);

        /// <summary>
        /// The approve async.
        /// </summary>     
        ///  /// <param name="appointmentId">
        /// The model.
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<Appointment> CheckOutAsync(int appointmentId, DateTime? checkedIn);

        /// <summary>
        /// The Appointment Log to sen messages and Emails through Hangfire
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Task<int> AddAppointmentHangfireAsync(AppointmentHangfireMapModel model);

        /// <summary>
        /// The fetch salucro pending transactions
        /// </summary>
        /// <returns></returns>
        public Task<IEnumerable<AppointmentTransactionModel>> FetchPendingSalucroTransactions();

        /// <summary>
        /// The update salucro payment status
        /// </summary>
        /// <returns></returns>
        public Task<int> UpadateSalucroPaymentStatusAsync(int respectiveId);

        /// <summary>
        /// The update salucro status check progress
        /// </summary>
        /// <returns></returns>
        public Task<int> UpdateSalucroStatusCheckProgress(int respectiveId, bool statusCheckInProgress);

        /// <summary>
        /// The Appointment Log to sen messages and Emails through Hangfire
        /// </summary>
        /// <param name="appointmentId"></param>
        /// <returns></returns>
        public Task<AppointmentModel> FetchForInvoiceAsync(int appointmentId, string status);

        public Task<int> CancelAppointmentAsync(AppointmentModel model, string type, string transaction, string transactionId, int? salucroStatusCode, string salucroTransactionId, int? modifiedBy, string reason);

        /// <summary>
        /// The Appointment Log to sen messages and Emails through Hangfire
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Task<int> RefundAppointmentCancelAmountAsync(AppointmentModel model);

        /// <summary>
        /// The find patient appointment
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Task<IEnumerable<AppointmentModel>> FindPatientAppointmentAsync(PatientAppointmentFilterModel model);

        /// <summary>
        /// The find patient appointment
        /// </summary>
        /// <returns></returns>
        public Task<IEnumerable<AppointmentTransactionModel>> FetchTransactionDataAsync(int logId);

        /// <summary>
        /// The find patient appointment
        /// </summary>
        /// <returns></returns>
        public Task<IEnumerable<AppointmentTransactionModel>> FetchTransactionAsync(int appointmentId, int type);

        /// <summary>
        /// The find patient appointment
        /// </summary>
        /// <returns></returns>
        public Task<int> CompletePartialPaymentAsync(AppointmentModel model);


        /// <summary>
        /// The fetch async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<IEnumerable<AppointmentModel>> FetchViewAsync(AppointmentFilterModel model);


        /// <summary>
        /// The fetch async.
        /// </summary>
        /// <param name="appointmentIds">The appointmentIds.</param>
        /// <param name="reason">The reason.</param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> CancelAllAsync(string appointmentIds, string reason);

        /// <summary>
        /// The reschedule async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <param name="appointmentDate">
        /// The appointment date.
        /// </param>
        /// <param name="appointmentTime">
        /// The appointment time.
        /// </param>
        /// <param name="appointmentNotes">
        /// The appointment Notes.
        /// </param>
        /// <param name="modifiedBy">
        /// The modified by.
        /// </param>
        /// <param name="providerId">
        /// The provider id.
        /// </param>
        /// <param name="providerLocationId">
        /// The provider location id.
        /// </param>
        /// <param name="departmentId">
        /// The department id.
        /// </param>
        /// <param name="locationId"></param>
        /// <param name="tokenNumber"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        Task<int> RescheduleAllAsync(string appointmentIds, DateTime appointmentDate, TimeSpan appointmentTime, TimeSpan appointmentEndTime, string appointmentNotes, int modifiedBy, int providerId, int providerAvailabilityId, int consultationTypeId, int? departmentId, int locationId, string? tokenNumbers, int? specializationId, string? appointmentTimings, string? AppointmentEndTimings,  int? visitTypeId, int? chargeTypesId, decimal amount, decimal total, decimal discount);


        /// <summary>
        /// The find async.
        /// </summary>
        /// <param name="id">
        /// The patient id.
        /// </param>
        /// <returns>
        /// The no. of appointment count for today <see cref="Task"/>.
        /// </returns>

        Task<int> GetAppointmentCountForTodayAsync(int id);
    }
}
