namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Shared.EntityModels;

    /// <inheritdoc />
    public class PatientInsuranceServices : IPatientInsuranceService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IPatientInsuranceService" />
        public PatientInsuranceServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public Task<IEnumerable<PatientInsuranceModel>> FetchAsync(int patientId)
        {
            var where = $@" WHERE patins.""Active"" IS TRUE AND patins.""PatientId"" = {patientId}";
            var query = $@"SELECT patins.*,IC.""FullName"" AS ""InsuranceCompanyName"" FROM ""PatientInsurance"" patins JOIN ""InsuranceCompany"" IC ON IC.""InsuranceCompanyId"" = patins.""InsuranceCompanyId"" {where} ORDER BY patins.""PatientInsuranceId"" DESC";
            return this.unitOfWork.Current.QueryAsync<PatientInsuranceModel>(query);
        }
       

     

        /// <inheritdoc />
        public async Task<int> AddAsync(PatientInsuranceModel model)
        {
            try {
                //var checkIf = await this.CheckInsuranceAsync(model.InsuranceCompanyId, (int)model.PatientId, (int)model.PatientInsuranceId);

                var checkIf = await this.CheckInsuranceAsync((int)model.InsuranceCompanyId, (int)model.PatientId, (int)model.PatientInsuranceId);
                if (checkIf != 0)
                {
                    return -1;
                }

                var patientInsurance = new PatientInsurance
                {
                    PatientId = (int)model.PatientId,
                    //                    InsuranceCompanyId = model.InsuranceCompanyId,

                    InsuranceCompanyId = (int)model.InsuranceCompanyId,
                    //                    InsuranceTypeId = model.InsuranceTypeId,

                    InsuranceTypeId = (int)model.InsuranceTypeId,
                    CardNo = model.CardNo,
                    //                    Validity = model.Validity,

                    Validity = (DateTime) model.Validity,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.UtcNow,
                    Active = true,
                };

                return await this.unitOfWork.PatientInsurances.InsertAsync(patientInsurance);
            }
            catch (Exception e)
            {

            }
            return 0;
        }

        /// <inheritdoc />
        public async Task<int> UpdateAsync(PatientInsuranceModel model)
        {
            //            var checkIf = await this.CheckInsuranceAsync(model.InsuranceCompanyId, (int)model.PatientId, (int)model.PatientInsuranceId);

            var checkIf = await this.CheckInsuranceAsync((int)model.InsuranceCompanyId, (int)model.PatientId, (int)model.PatientInsuranceId);
            if (checkIf != 0)
            {
                return -1;
            }

            var patientInsurance = await this.unitOfWork.PatientInsurances.FindAsync(m => m.PatientInsuranceId == model.PatientInsuranceId);
            //            patientInsurance.InsuranceCompanyId = model.InsuranceCompanyId;

            patientInsurance.InsuranceCompanyId =(int)model.InsuranceCompanyId;
            patientInsurance.CardNo = model.CardNo;
            patientInsurance.PatientId = (int)model.PatientId;
            //            patientInsurance.Validity = model.Validity;

            patientInsurance.Validity =(DateTime)model.Validity;
            patientInsurance.ModifiedBy = model.ModifiedBy;
            patientInsurance.ModifiedDate = DateTime.UtcNow;

            return await this.unitOfWork.PatientInsurances.UpdateAsync(patientInsurance);
        }

        /// <inheritdoc />
        public async Task<int> DeleteAsync(int patientInsuranceId)
        {
            var query = $@"DELETE FROM ""PatientInsurance"" WHERE ""PatientInsuranceId""= {patientInsuranceId} ";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <summary>
        /// The check insurance async.
        /// </summary>
        /// <param name="insuranceCompanyId">
        /// The insurance company id.
        /// </param>
        /// <param name="patientId">
        /// The patient Id.
        /// </param>
        /// <param name="patientInsuranceId">
        /// The patient insurance id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        private Task<int> CheckInsuranceAsync(int insuranceCompanyId, int patientId, int patientInsuranceId) => this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""PatientInsuranceId"") FROM ""PatientInsurance"" WHERE ""InsuranceCompanyId"" = '{insuranceCompanyId}' AND  ""PatientId"" = '{patientId}' AND  ""PatientInsuranceId"" <> '{patientInsuranceId}'");
    }
}