protected override async Task <Card> HandleCore(DisabilitySheetHookContext context)
        {
            if (_options.AvailableKindDisabilityCodes.Any(
                    a => a.Equals(context.KindDisabilityCode, StringComparison.CurrentCultureIgnoreCase)) == false)
            {
                return(new Card("Правило для указанного вида нетрудоспособности не проверяеться", Indicator.Info, new Link("")));
            }

            var isTuberculosisConditioninRequest =
                _options.TuberculosisMkbDiagnosis.Any(t => context.DiagnosisCode.ToLowerInvariant().StartsWith(t));



            var requestingDays = (context.TreatmentEnd.Date - context.TreatmentStart.Date).Days + 1;


            var calculateDaysSql =
                "CASE WHEN start< (current_date - interval '1 year') THEN \"end\"::date-(current_date - interval '1 year')::date+1  ELSE \"end\"::date-start::date+1 END";


            var sqlGetDays =
                $@"SELECT SUM(CASE WHEN LOWER(diagnosis_code) SIMILAR TO '({string.Join("|", _options.TuberculosisMkbDiagnosis)})%'  
                   THEN {(isTuberculosisConditioninRequest ? calculateDaysSql : 0.ToString())} 
                 ELSE {(isTuberculosisConditioninRequest == false ? calculateDaysSql : 0.ToString())} END) AS days 
                FROM episodeofcare eoc 
                INNER JOIN episodeofcare_condition ecc ON ecc.episodeofcare_id = eoc.id 
                INNER JOIN condition ec ON ec.id = ecc.condition_id AND ec.status = 'Confirmed'
                    INNER JOIN composition com ON com.episodeofcare_id = eoc.id  and  com.status != 'entered-in-error' " +
                "WHERE \"end\">(current_date - interval '1 year') and eoc.status!='cancelled' and com.subject_id = @PatientId and eoc.id!=@EpisodeOfCareId";


            var queryParam = new
            {
                PatientId = context.FreedPersonId,
                context.EpisodeOfCareId,
            };

            var query = (
                await _unitOfWork.QueryAsync(
                    (connection, transaction) =>
                    connection.QueryAsync <long?>(sqlGetDays, queryParam, transaction))).First();
            var queryResult        = query ?? 0;
            var usedDaysInLastYear = queryResult;
            var maximumYearDays    = isTuberculosisConditioninRequest
                ? _options.MaximumTuberculosisDaysCount
                : _options.MaximumDaysCountWithoutTuberculosis;


            if (usedDaysInLastYear + requestingDays > maximumYearDays)
            {
                return(new Card("Превышение общего периода нетрудоспособности за последние 12 месяцев.", Indicator.HardStop, new Link("")));
            }

            if (usedDaysInLastYear + requestingDays >= maximumYearDays - _options.DaysPriorToExcees)
            {
                return(new Card("Превышение общего периода нетрудоспособности за последние 12 месяцев.", Indicator.Warning, new Link("")));
            }

            return(new Card("Правило пройдено успешно", Indicator.Success, new Link("")));
        }
        protected override async Task <Card> HandleCore(DisabilitySheetHookContext context)
        {
            var sql = @"
                        SELECT
                            eoc.start as beginDate,
                            eoc.end as endDate
                        FROM episodeofcare  eoc
                        JOIN composition c on c.episodeofcare_id = eoc.id 
                        where c.status != 'entered-in-error' 
                                and eoc.status!='cancelled' 
                                and eoc.patient_id = @PatientId 
                                and (eoc.id!=@EpisodeOfCareId or @EpisodeOfCareId is null);
                        ";

            //temporary data
            var hardStopQueryParameters = new
            {
                context.PatientId,
                context.EpisodeOfCareId
            };

            var hardStopRange = new DateRange()
            {
                BeginDate = context.TreatmentStart,
                EndDate   = context.TreatmentEnd
            };

            var existingDisabilitiesPeriods = (await _unitOfWork.QueryAsync(
                                                   (connection, transaction) => connection.QueryAsync <DateRange>(sql, hardStopQueryParameters, transaction))).ToList();


            if (existingDisabilitiesPeriods.Any(t => t.Intersects(hardStopRange)))
            {
                return(new Card("Для Указанного листка нетрудоспособности существует листок с пересекающимся периодом", Indicator.HardStop, new Link("")));
            }

            var warningRange = new DateRange()
            {
                BeginDate = context.TreatmentStart.AddDays(-(_options.LeftPeriodIncrementForWarningDays + 1)),
                EndDate   = context.TreatmentEnd.AddDays(+(_options.LeftPeriodIncrementForWarningDays + 1))
            };

            if (existingDisabilitiesPeriods.Any(t => t.Intersects(warningRange)))
            {
                return(new Card("Для Указанного листка нетрудоспособности существует листок с пересекающимся периодом", Indicator.Warning, new Link("")));
            }

            return(new Card("Правило пройдено успешно", Indicator.Success, new Link("")));
        }
        protected override async Task<Card> HandleCore(DisabilitySheetHookContext context)
        {


            if (context.CompositionCreating <= context.TreatmentStart)
                return new Card("Правило пройдено успешно", Indicator.Success, new Link(""));

            if (string.Equals(context.TreatmentModeCode, TreatmentModeInpatient))
            {
                return new Card("Дата выписки листка нетрудоспособности не должна превышать дату освобождения от работы при выполнении условия -  режим должен быть стационарный.", Indicator.Success, new Link(""));
            }

            if (context.VkkDates != null)
            {
                if (string.Equals(context.TreatmentModeCode, TreatmentModeMmbulatory) && context.VkkDates.Any(d => d.Date == context.CompositionCreating.Date))
                {
                    return new Card("Дата выписки листка нетрудоспособности не должна превышать дату освобождения от работы при выполнении условия -  режим амбулаторный и проведено ВКК в день выписки.", Indicator.Success, new Link(""));
                }
            }


            return new Card("Дата выписки листка нетрудоспособности не должна превышать дату освобождения от работы", Indicator.HardStop, new Link(""));

        }
        protected override async Task <Card> HandleCore(DisabilitySheetHookContext context)
        {
            if (_options.AvailableKindDisabilityCodes.Any(
                    a => a.Equals(context.KindDisabilityCode, StringComparison.CurrentCultureIgnoreCase)) == false)
            {
                return(null);
            }
            //Поскольку правило звучит как Превышение периода непрерывного срока нетрудоспособности, то нужно учитывать и предидущие и последующие листки нетрудоспособности
            var sql = $@"SELECT 
                            eoc.start as beginDate, 
                            eoc.end as endDate,
                            LOWER(diagnosis_code) SIMILAR TO '({string.Join("|", _options.TuberculosisMkbDiagnosis)})%' as IsTuberculosis
                        FROM episodeofcare eoc  
INNER JOIN episodeofcare_condition ecc ON ecc.episodeofcare_id = eoc.id 
                INNER JOIN condition ec ON ec.id = ecc.condition_id AND ec.status = 'final'
                    INNER JOIN composition com ON com.episodeofcare_id = eoc.id and com.status!='entered-in-error' 
                    WHERE eoc.status!='cancelled' and com.subject_id = @PatientId and eoc.id!=@EpisodeOfCareId";

            var existingDisabilitiesPeriods = (await _unitOfWork.QueryAsync(
                                                   (connection, transaction) => connection.QueryAsync <ThreatmentRange>(sql, new { PatientId = context.FreedPersonId, context.EpisodeOfCareId }, transaction))).ToList();

            var isTuberculosisConditioninRequest =
                _options.TuberculosisMkbDiagnosis.Any(t => context.DiagnosisCode.ToLowerInvariant().StartsWith(t));

            existingDisabilitiesPeriods = existingDisabilitiesPeriods.Where(d => d.IsTuberculosis == isTuberculosisConditioninRequest).OrderBy(p => p.BeginDate).ToList();

            var continuousDisabilitiesPeriods = new List <ThreatmentRange>();


            DateTime?startDate = context.TreatmentStart;

            //Выбираем непрерывные переоды предшествующие
            while (startDate != null)
            {
                var previosPeriod =
                    existingDisabilitiesPeriods.FirstOrDefault(p => p.EndDate <= startDate.Value && (startDate.Value - p.EndDate).TotalHours <= 24);
                if (previosPeriod != null)
                {
                    continuousDisabilitiesPeriods.Add(previosPeriod);
                    startDate = previosPeriod.BeginDate;
                    continue;
                }
                startDate = null;
            }
            DateTime?endDate = context.TreatmentEnd;

            //Выбираем непрерывные переоды последующие
            while (endDate != null)
            {
                var nextPeriod =
                    existingDisabilitiesPeriods.FirstOrDefault(p => p.BeginDate >= endDate.Value && (p.BeginDate - endDate.Value).TotalHours <= 24);
                if (nextPeriod != null)
                {
                    continuousDisabilitiesPeriods.Add(nextPeriod);
                    endDate = nextPeriod.EndDate;
                    continue;
                }
                endDate = null;
            }
            continuousDisabilitiesPeriods.Add(new ThreatmentRange()
            {
                EndDate = context.TreatmentEnd, BeginDate = context.TreatmentStart, IsTuberculosis = _options.TuberculosisMkbDiagnosis.Any(d => d.Equals(context.DiagnosisCode, StringComparison.OrdinalIgnoreCase))
            });

            //Выбираем из списка переодов те которые граничат с текущим с разницей в день
            //И по критерию туберкулезности должны соответствовать контексту
            //var continuousDisabilitiesPeriods = existingDisabilitiesPeriods.Where(
            //    p => (p.BeginDate - context.TreatmentStart).Hours <= TimeSpan.FromDays(1).Hours ||
            //         (p.EndDate - context.TreatmentEnd).Hours <= TimeSpan.FromDays(1).Hours).Where(d => d.IsTuberculosis == isTuberculosisConditioninRequest).ToList();



            var continiousDays  = continuousDisabilitiesPeriods.Sum(p => (p.EndDate - p.BeginDate).Days + 1);
            var maximumYearDays = isTuberculosisConditioninRequest ? _options.MaximumTuberculosisDaysCount : _options.MaximumDaysCountWithoutTuberculosis;

            if (continiousDays > maximumYearDays)
            {
                return(new Card("Превышение периода непрерывного срока нетрудоспособности", Indicator.HardStop, new Link("")));
            }

            if (continiousDays >= maximumYearDays - _options.DaysPriorToExcees)
            {
                return(new Card("Превышение периода непрерывного срока нетрудоспособности", Indicator.Warning, new Link("")));
            }

            return(new Card("Правило пройдено успешно", Indicator.Success, new Link("")));
        }
        protected override async Task <Card> HandleCore(DisabilitySheetHookContext context)
        {
            //Если вид нетрудоспособности не уход за больным членом семьи то правило не проверяем
            if (string.Equals(context.KindDisabilityCode, KindDisabilityCode) == false)
            {
                return(null);
            }


            if ((context.TreatmentEnd - context.TreatmentStart).Days + 1 > 14)
            {
                return(new Card("Больничный листок по уходу за больным членом семьи не должен превышать 14 дней", Indicator.HardStop, new Link("")));
            }

            var sql = @"
                        select 
                            (select EXTRACT(YEAR FROM age(cast(pat.date_birth as date))) from patient pat where pat.id = @PatientId ) as  age,
                            (
	                            SELECT
	                               SUM(DATE_PART('day', eoc.end::timestamp - eoc.start::timestamp)+1)   
	                            FROM composition com
	                            JOIN episodeofcare eoc on com.episodeofcare_id = eoc.id
	                            FULL OUTER JOIN patient pat on eoc.patient_id = pat.id
	                            where (
			                            (com.status != 'entered-in-error' and eoc.status!='cancelled' and com.claim_id = @ClaimId) 
			                            or com.claim_id is null or @ClaimId is null
		                            )  
	                            and (eoc.id!=@EpisodeOfCareId or eoc.id is null) 
	                            and pat.id = @PatientId
	                            Group by pat.id
                            ) as  dayscount
                            ;
                        ";

            var sqlParameters = new
            {
                context.ClaimId,
                context.EpisodeOfCareId,
                context.PatientId
            };
            var fromDataBase = (await _unitOfWork.QueryAsync(
                                    (connection, transaction) => connection.QuerySingleOrDefaultAsync <dynamic>(sql, sqlParameters, transaction)));

            //Добавляем период Eoc Пришедший в cds
            var duration = (context.TreatmentEnd - context.TreatmentStart).Days + 1 + (fromDataBase == null ? 0 : fromDataBase.dayscount ?? 0);


            if (duration > 14)
            {
                return(new Card("Больничный листок по уходу за больным членом семьи не должен превышать 14 дней", Indicator.HardStop, new Link("")));
            }

            if (fromDataBase == null || fromDataBase?.age == null)
            {
                if (duration <= 7)
                {
                    return(new Card("Правило пройдено успешно", Indicator.Success, new Link("")));
                }
                if (duration <= 14)
                {
                    return(new Card("Возраст пациента неизвестен. Больничный не может быть более 14 дней для детей до 14 лет, в остальных случаях 7 дней", Indicator.Warning, new Link("")));
                }
            }


            if (fromDataBase?.age > 14)
            {
                if (context.VkkDates.Any() == false)
                {
                    return(new Card("Для Выписки больничного листка пациенту, чей возраст больше 14 лет, должно быть проведено ВКК", Indicator.HardStop, new Link("")));
                }
                if (duration > 7)
                {
                    return(new Card("Больничный листок по уходу за больным членом семьи не должен превышать 7 дней", Indicator.HardStop, new Link("")));
                }
            }

            return(new Card("Правило выполнено успешно", Indicator.Success, new Link("")));
        }