public void Biweekly_Premiums_Are_Calculated()
        {
            var plan = new Plan().WithPremium(PremiumType.Individual, Frequency.Biweekly);
            var engine = new YearlyPlanCostEngine();

            var yearlyCost = engine.CalculateYearlyCost(plan, 0, PremiumType.Individual);

            Assert.AreEqual(plan.Premium(PremiumType.Individual).Cost * 26, yearlyCost);
        }
        public void Medical_Cost_Equal_To_Individual_Deductible_Is_Calculated()
        {
            var plan = new Plan().WithPremium(PremiumType.Individual, Frequency.Monthly).WithDeductibles().WithCoinsurance().WithOutOfPocketMax();
            var engine = new YearlyPlanCostEngine();

            var yearlyCost = engine.CalculateYearlyCost(plan, plan.IndividualDeductible, PremiumType.Individual);

            var premium = plan.Premium(PremiumType.Individual);
            var premiumCost = premium.Cost * 12;

            Assert.AreEqual(premiumCost + plan.IndividualDeductible, yearlyCost);
        }
        public decimal CalculateYearlyCost(Plan plan, decimal totalMedicalCosts, PremiumType premiumType, DeductibleType deductibleType = DeductibleType.Individual)
        {
            var premium = plan.Premium(premiumType);
            var premiumCost = premium.Cost * PremiumMultiplierFactory.GetMultipler(premium.Frequency);

            var deductibleAmount = plan.Deductible(deductibleType);
            var costsDuringDeductible = Math.Min(deductibleAmount, totalMedicalCosts);

            var outOfPocketMax = plan.OutOfPocketMax(deductibleType);
            var costsUnderOutOfPocketMax = Math.Min((totalMedicalCosts - costsDuringDeductible) * plan.CoinsurancePercentage, outOfPocketMax - deductibleAmount);

            return premiumCost + costsDuringDeductible + costsUnderOutOfPocketMax;
        }
        public void Medical_Cost_Equal_To_Family_Deductible_Is_Calculated()
        {
            var premiumType = PremiumType.IndividualSpouseAndChildren;
            var plan = new Plan().WithPremium(premiumType, Frequency.Monthly).WithDeductibles().WithCoinsurance().WithOutOfPocketMax();
            var engine = new YearlyPlanCostEngine();

            var yearlyCost = engine.CalculateYearlyCost(plan, plan.FamilyDeductible, premiumType, DeductibleType.Family);

            var premium = plan.Premium(premiumType);
            var premiumCost = premium.Cost * 12;

            Assert.AreEqual(premiumCost + plan.FamilyDeductible, yearlyCost);
        }
        public void Cost_That_Exceeds_Individual_OopMax_Is_Calculated()
        {
            var premiumType = PremiumType.Individual;
            var plan = new Plan().WithPremium(premiumType, Frequency.Monthly).WithDeductibles().WithCoinsurance().WithOutOfPocketMax();
            var engine = new YearlyPlanCostEngine();

            var costToEqualOopMax = plan.IndividualDeductible + ((plan.IndividualOutOfPocketMax - plan.IndividualDeductible) / plan.CoinsurancePercentage);

            var yearlyCost = engine.CalculateYearlyCost(plan, costToEqualOopMax + 100, premiumType, DeductibleType.Individual);

            var premium = plan.Premium(premiumType);
            var premiumCost = premium.Cost * 12;

            Assert.AreEqual(premiumCost + plan.IndividualOutOfPocketMax, yearlyCost);
        }
        public void Yearly_Cost_Equal_To_Family_OopMax_Is_Calculated()
        {
            var premiumType = PremiumType.IndividualSpouseAndChildren;
            var plan = new Plan().WithPremium(premiumType, Frequency.Monthly).WithDeductibles().WithCoinsurance().WithOutOfPocketMax();
            var engine = new YearlyPlanCostEngine();

            var costToEqualOopMax = plan.FamilyDeductible + ((plan.FamilyOutOfPocketMax - plan.FamilyDeductible)/ plan.CoinsurancePercentage);

            var yearlyCost = engine.CalculateYearlyCost(plan, costToEqualOopMax, premiumType, DeductibleType.Family);

            var premium = plan.Premium(premiumType);
            var premiumCost = premium.Cost * 12;

            Assert.AreEqual(premiumCost + plan.FamilyOutOfPocketMax, yearlyCost);
        }