using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using DataContracts;

namespace Ato.EN.IntegrationServices.CodeGenerationRDTIS
{
    public partial class RDTIS2023Validator
    {
        #region Manual Rules - Rules marked for manual coding

        static int expenditureCap = Int32.Parse("150,000,000", System.Globalization.NumberStyles.Number); //ExpenditureCap = $150 million, Constant Tab in VR Artefacts;
        //static int refundableCap = Int32.Parse("4,000,000", System.Globalization.NumberStyles.Number);  //RefundableCap = 4000000, Constant Tab in VR Artefacts;
        static decimal refundablePremium = 0.185M; //18.5%, Constant Tab in VR Artefacts;


        #region VR.ATO.RDTIS.438109

        /*  VR.ATO.RDTIS.438109
                    If Tax rate is provided, then the Tax rate must be one of the following values 30, 30.00, 25, 25.00

                Legacy Rule Format:
                    IF [RDTIS78] <> NULL AND ([RDTIS78] <> SET("30", "30.00", "25", "25.00"))
                       RETURN VALIDATION MESSAGE
                    ENDIF

            Technical Business Rule Format:
                    ^RDTIS78 <> NULL AND (NotInSet(^RDTIS78, '"30", 30, "25", 25'))

        Data Elements:
    
            ^RDTIS78 = RDTIS:RP:TaxRate.Designation.Rate
            */
        public void VRATORDTIS438109(List<ProcessMessageDocument> response, RDTIS2023 reportIn)
        {
            ProcessMessageDocument processMessage;
            bool assertion;

            assertion = (report.RDTIS78 != null && !(IsMatch(report.RDTIS78.GetValueOrDefault().ToString(), @"^(30|30.00|25|25.00)$", RegexOptions.IgnoreCase)));
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.RDTIS.438109",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Field incorrect format. Tax rate must be one of the following values 30, 30.00, 25, 25.00",
                    Location = "/tns:RDTIS/tns:RP/tns:TaxRateDesignationR",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.RDTIS.438109" } },
                };


                processMessage.Parameters.Add(new ProcessMessageParameter
                { Name = "RDTIS78", Value = GetValueOrEmpty(report.RDTIS78) });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.RDTIS.438109

        #region VR.ATO.RDTIS.438111

        /*  VR.ATO.RDTIS.438111
                    If R&D intensity is provided, then a valid range for R&D intensity is 000.01 - 100.00

                Legacy Rule Format:
                    IF [RDTIS82] <> NULL AND ([RDTIS82] <> SET(0.01 - 100.00))
                       RETURN VALIDATION MESSAGE
                    ENDIF

            Technical Business Rule Format:
                    ^RDTIS82 <> NULL AND (NotInSet(^RDTIS82, '0.01-100.00'))

        Data Elements:
    
            ^RDTIS82 = RDTIS:RP:NonRefundableTaxOffset:Miscellaneous.ResearchAndDevelopmentIntensity.Rate
            */
        public void VRATORDTIS438111(List<ProcessMessageDocument> response, RDTIS2023 reportIn)
        {
            ProcessMessageDocument processMessage;
            bool assertion;

            assertion = (report.RDTIS82 != null && (report.RDTIS82.GetValueOrDefault() < 0.0001M || report.RDTIS82.GetValueOrDefault() > 100.00M));
            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.RDTIS.438111",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Field incorrect format. Valid range for R&D Intensity is 0.01 - 100.00",
                    Location = "/tns:RDTIS/tns:RP/tns:NonRefundableTaxOffset/tns:MiscellaneousResearchAndDevelopmentIntensityR",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.RDTIS.438111" } },
                };


                processMessage.Parameters.Add(new ProcessMessageParameter
                { Name = "RDTIS82", Value = GetValueOrEmpty(report.RDTIS82) });

                response.Add(processMessage);
            }
        }
        #endregion // VR.ATO.RDTIS.438111

        #endregion Manual Rules - Rules marked for manual coding 

        #region Part E Calculation Function 

        #region CalcRefundableOffset

        /*
        IF ([RDTIS45] < ExpenditureCap) THEN
             [RDTIS45] * ([RDTIS78] + RefundablePremium)
        ELSE 
             (ExpenditureCap * ([RDTIS78] + RefundablePremium)) + (([RDTIS45] - ExpenditureCap) * [RDTIS78])
        ENDIF
        */
        private decimal CalcRefundableOffset(RDTIS2023 report, bool isRefundableOffset)
        {
            if (report.RDTIS45 < expenditureCap)
            {
                return (decimal)(report.RDTIS45.GetValueOrDefault() * ((report.RDTIS78.GetValueOrDefault() / 100) + refundablePremium));
            }
            else
            {
                return (decimal)((expenditureCap * ((report.RDTIS78.GetValueOrDefault() / 100) + refundablePremium)) + ((report.RDTIS45.GetValueOrDefault() - expenditureCap) * (report.RDTIS78.GetValueOrDefault() / 100)));
            }
        }

        #endregion

        #region calcNonRefundableOffset

        /*
          IF ([RDTIS47] > ExpenditureCap) THEN
                 Intensity = (ExpenditureCap / [RDTIS81])
                 ExcessOffset = ([RDTIS47] - ExpenditureCap) * [RDTIS78]
            ELSE
                 Intensity = ([RDTIS47] / [RDTIS81])
                 ExcessOffset = 0
            ENDIF            
           
            IF (Intensity > 0 AND Intensity <= T1Intensity) THEN
                 IF ([RDTIS47] > ExpenditureCap) THEN
                      T1Deductions = ExpenditureCap
                 ELSE
                      T1Deductions = [RDTIS47]
                 ENDIF
            ELSE
                 T1Deductions = T1Intensity * [RDTIS81]
                      IF [RDTIS47] > ExpenditureCap THEN
                           T2Deductions = (ExpenditureCap - T1Deductions)
                      ELSE
                           T2Deductions = ([RDTIS47] - T1Deductions)
                      ENDIF
            ENDIF

            T1Offset = (T1Deductions * ([RDTIS78] + T1Premium))
            T2Offset = (T2Deductions * ([RDTIS78] + T2Premium))

            NonRefundableOffset = T1Offset + T2Offset + ExcessOffset

         */
        private decimal calcNonRefundableOffset(RDTIS2023 report)
        {
            decimal intensity = 0, excessOffset = 0;
            // T1,T2  Deduction Calculation Variable
            decimal t1Intensity = 0.02M; // 2%;
            //decimal t2Intensity = 0.02+M; // 2+% ;  
            decimal t1Deductions = 0, t2Deductions = 0;
            // Premium %
            decimal t1Premium = 0.085M; // 8.5%;
            decimal t2Premium = 0.165M; // 16.5%;
            
            //decimal taxRate = (report.RDTIS78.GetValueOrDefault() / 100); //RDTIS78

            // intensity and excessOffset Calculation
            if (report.RDTIS47.GetValueOrDefault() > expenditureCap)
            {
                if (report.RDTIS81.GetValueOrDefault() > 0)
                    intensity = (expenditureCap / report.RDTIS81.GetValueOrDefault());
                excessOffset = (report.RDTIS47.GetValueOrDefault() - expenditureCap) * (report.RDTIS78.GetValueOrDefault() / 100);
            }
            else
            {
                if (report.RDTIS81.GetValueOrDefault() > 0)
                    intensity = (report.RDTIS47.GetValueOrDefault() / report.RDTIS81.GetValueOrDefault());
                excessOffset = 0;
            }
            
            // T1,T2 Deduction Calculation             
            if (intensity > 0 && intensity <= t1Intensity) // Tier1 deduction
            {
                t1Deductions = report.RDTIS47.GetValueOrDefault() > expenditureCap ? expenditureCap : report.RDTIS47.GetValueOrDefault();
            }
            else
            {
                t1Deductions = t1Intensity * report.RDTIS81.GetValueOrDefault();
                //IF[RDTIS47] > ExpenditureCap THEN
                //         T2Deductions = (ExpenditureCap - T1Deductions)
                //      ELSE
                //           T2Deductions = ([RDTIS47] - T1Deductions)
                //      ENDIF
                //if (intensity > t1Intensity )//&& intensity <= t2Intensity) // Tier2 deduction
                //{
                    t2Deductions = report.RDTIS47.GetValueOrDefault() > expenditureCap ? (expenditureCap - t1Deductions) : (report.RDTIS47.GetValueOrDefault() - t1Deductions);
                //}
                //else
                //{
                //    t2Deductions = (t2Intensity * report.RDTIS81.GetValueOrDefault()) - t1Deductions;
                     
                //}
            }
            // t1Offset + t2Offset + excessOffset  
            return Math.Round(((t1Deductions * ((report.RDTIS78.GetValueOrDefault() / 100) + t1Premium)) + (t2Deductions * ((report.RDTIS78.GetValueOrDefault() / 100) + t2Premium)) + excessOffset), 2, MidpointRounding.AwayFromZero);
        }

        #endregion

        #endregion 
    }
}
