using Ato.CD.Inbound.Shared;
using Ato.CD.Inbound.Shared201802;
using Ato.EN.IntegrationServices.CodeGenerationCGTS;
using Ato.EN.IntegrationServices.CodeGenerationCTR;
using DataContracts;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using VaTS;

namespace Ato.CD.Inbound.CTR202602
{
    internal class CrossFormValidatorCGTS : ICrossFormValidator
    {
        private CTR2026 ParentDocument { get; }
        private CGTS2018 ChildDocument { get; }
        private List<Context> Contexts { get; }
        public List<ProcessMessageDocument> Response { get; private set; }

        internal CrossFormValidatorCGTS(CTR2026 report, BusinessDocument childDocument)
        {
            ParentDocument = report;
            ChildDocument = (CGTS2018)childDocument.ConsumedReport;
            Contexts = ChildDocument.GetContexts();
            Response = new List<ProcessMessageDocument>();
        }

        public List<ProcessMessageDocument> ValidateCrossFormRules()
        {
            //Parent Cross From Validation Rules
            VRATOCTR428027();
            VRATOCTR430031();
            VRATOCTR428098();
            VRATOCTR430023();
            VRATOGEN438022();
            VRATOGEN438023();
            VRATOGEN438024();
            VRATOGEN438025();
            VRATOGEN438026();
            VRATOGEN438027();
            VRATOGEN438028();

            //Child Cross From Validation Rules
            VRATOCGTS402173();
            VRATOCGTS402174();
            VRATOCGTS402203();
            VRATOCGTS402226();
            VRATOCGTS402230();
            VRATOCGTS402240();
            VRATOGEN402009();
            VRATOGEN438000();
            VRATOGEN438001();

            return Response;
        }

        #region VR.ATO.CTR.428027

        /*  VR.ATO.CTR.428027
        Companies cannot claim CGT discount unless they are life insurance companies or friendly societies or the company type is corporate unit trusts or public trading trusts and cannot claim if the entity is head company of a consolidated group.

        Legacy Rule Format:
        IF (([CTR49] <> SET ("63100","62400") AND 
        [CTR52] <> SET ("054", "174")) OR ([CTR52] = SET ("054", "174") AND [CTR53] = "1")) AND [CGTS126] > 0
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
      
        ^CTR49 = CTR:RP:OrganisationDetails.OrganisationIndustry2006Extended.Code
        ^CTR52 = CTR:RP:OrganisationDetails.OrganisationType.Code
        ^CTR53 = CTR:RP:OrganisationDetails.TaxConsolidationStatus.Code
        ^CGTS126 = CGTS:RP.Applied:TaxConcession.CapitalGains.DiscountTotal.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCTR428027()
        {
            ProcessMessageDocument processMessage;
            bool assertion =
                (!IsMatch(ParentDocument.CTR49, "^(63100|62400)$", RegexOptions.IgnoreCase) &&
                 !IsMatch(ParentDocument.CTR52, "^(054|174)$", RegexOptions.IgnoreCase) ||
                 IsMatch(ParentDocument.CTR52, "^(054|174)$") && ParentDocument.CTR53 == "1") &&
                 ChildDocument.CGTS126.GetValueOrDefault() > 0;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.438052",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Total CGT discount applied not applicable",
                    LongDescription = @"Companies cannot claim CGT discount unless they are life insurance companies or friendly societies or the company type is corporate unit trusts or public trading trusts and cannot claim if the entity is head company of a consolidated group",
                    Location = "/xbrli:xbrl/tns:OrganisationDetails.OrganisationType.Code",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428027" } },
                    DocumentSequence = "parent_doc"
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR49", Value = ParentDocument.CTR49 });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR52", Value = ParentDocument.CTR52 });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR53", Value = ParentDocument.CTR53 });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS126", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS126) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CTR.428027

        #region VR.ATO.CTR.430031

        /*  VR.ATO.CTR.430031
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Intercompany rollover Subdivision 126B", then Capital gains disregarded as a result of inter-company assets roll-over amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF ([CTR330] = "G - Inter-company roll-over") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS46] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS46 = CGTS:RP:Capital.Gains.InterCompanyAssetRolloverDeferral.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCTR430031()
        {
            if (!ChildDocument.CGTS46.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(G - Inter-company roll-over)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.CTR.430031",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Capital gains disregarded as a result of inter-company assets roll-over amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Intercompany rollover Subdivision 126B"", then Capital gains disregarded as a result of inter-company assets roll-over amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index + 1}]",
                            Parameters = new ProcessMessageParameters
                            { 
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.430031" }, 
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 } 
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.CTR.430031

        #region VR.ATO.CTR.428098

        /*  VR.ATO.CTR.428098
        Net capital gain in return must equal net capital gain in CGT schedule

        Legacy Rule Format:
        IF (COUNT(SCHEDULE = "CGTS") = 1) AND ([CTR91] <> [CGTS131])
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
        ^CTR91 = CTR:RP:Income.CapitalGainsNet.Amount
        ^CGTS131 = CGTS:RP:Income.CapitalGainsNet.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCTR428098()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR91.GetValueOrDefault() != ChildDocument.CGTS131.GetValueOrDefault();

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.430019",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Net capital gain in return must equal net capital gain in CGT schedule",
                    LongDescription = @"Net capital gain amount on the company return  must equal the net capital gain amount on the CGT schedule",
                    Location = "/xbrli:xbrl/tns:Income.CapitalGainsNet.Amount",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.428098" } },
                    DocumentSequence = "parent_doc"
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR91", Value = CTR2026Validator.GetValueOrEmpty(ParentDocument.CTR91) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS131", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS131) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CTR.428098

        #region VR.ATO.CTR.430023

        /*  VR.ATO.CTR.430023
        The net capital losses carried forward (including collectables) must be consistent between the income tax return and the CGT schedule

        Legacy Rule Format:
        IF [CTR176] <> NULL  AND (COUNT(SCHEDULE = "CGTS") = 1) AND ([CTR176] <> ([CGTS124] + [CGTS125]))
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR176 =  CTR:RP:Capital.Losses.CarriedForward.Net.Amount
        ^CGTS124 = CGTS:RP.Collectables.Unapplied(Instant):Capital.Losses.CarriedForward.Net.Amount
        ^CGTS125 = CGTS:RP.CGTOther.Unapplied(Instant):Capital.Losses.CarriedForward.Net.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCTR430023()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR176 != null && ParentDocument.CTR176.GetValueOrDefault() !=
                             ChildDocument.CGTS124.GetValueOrDefault() + ChildDocument.CGTS125.GetValueOrDefault();
            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CTR.430023",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Net capital losses carried forward to later income years incorrect",
                    LongDescription = @"Net capital losses carried forward to later income years on the company return  must equal the total net capital losses carried forward (including collectables) to later income years on the CGT schedule",
                    Location = "/xbrli:xbrl/tns:Capital.Losses.CarriedForward.Net.Amount",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CTR.430023" } },
                    DocumentSequence = "parent_doc"
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR176", Value = CTR2026Validator.GetValueOrEmpty(ParentDocument.CTR176) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS124", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS124) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS125", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS125) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CTR.430023

        #region VR.ATO.GEN.438022

        /*  VR.ATO.GEN.438022
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Small business active asset reduction (Subdivision 152-C)", then Small business active asset reduction amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "A - Small business active asset reduction") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS127] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
     
        CGTS127 = CGTS:RP:TaxConcession.CapitalGains.SmallBusinessActiveAssetReduction.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438022()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR330Collection != null &&
                       ParentDocument.CTR330Collection.Any(s => s.Equals("A - Small business active asset reduction")) &&
                       !ChildDocument.CGTS127.HasValue;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.GEN.438022",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Small business active asset reduction amount missing from CGT schedule",
                    LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Small business active asset reduction (Subdivision 152-C)"", then Small business active asset reduction amount on attached CGT schedule must be completed",
                    Location = "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438022" } },
                    DocumentSequence = "parent_doc"
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR176", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS127) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.GEN.438022

        #region VR.ATO.GEN.438023

        /*  VR.ATO.GEN.438023
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Small business retirement exemption (Subdivision152-D)", then Small business retirement exemption amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "B - Small business retirement exemption") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS128] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF
   
        Data Elements:
            
        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS128 = CGTS:RP:TaxConcession.CapitalGains.SmallBusinessRetirementExemption.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438023()
        {
            if (!ChildDocument.CGTS128.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(B - Small business retirement exemption)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.GEN.438023",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Small business retirement exemption amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Small business retirement exemption (Subdivision152-D)"", then Small business retirement exemption amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index + 1}]",
                            Parameters = new ProcessMessageParameters 
                            {
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438023" }, 
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 },
                                new ProcessMessageParameter { Name = "CGTS128", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS128) }
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.GEN.438023

        #region VR.ATO.GEN.438024

        /*  VR.ATO.GEN.438024
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Small business roll-over (Subdivision 152-E)", then Small business roll-over amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "C - Small business roll-over") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS129] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
            
        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS129 = CGTS:RP:TaxConcession.CapitalGains.SmallBusinessRollover.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438024()
        {
            if (!ChildDocument.CGTS129.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(C - Small business roll-over)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.GEN.438024",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Small business roll-over amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Small business roll-over (Subdivision 152-E)"", then Small business roll-over amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index + 1}]",
                            Parameters = new ProcessMessageParameters 
                            { 
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438024" },
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 },
                                new ProcessMessageParameter { Name = "CGTS129", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS129) }
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.GEN.438024

        #region VR.ATO.GEN.438025

        /*  VR.ATO.GEN.438025
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Small business 15 year exemption (Subdivision152-B)", then Small business 15 year exemption amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "D - Small business 15 year exemption") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS138] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS138 = CGTS:RP:TaxConcession.CapitalGains.SmallBusinessExemptionExempt.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438025()
        {
            if (!ChildDocument.CGTS138.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(D - Small business 15 year exemption)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.GEN.438025",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Small business 15 year exemption amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Small business 15 year exemption (Subdivision152-B)"", then Small business 15 year exemption amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index + 1}]",
                            Parameters = new ProcessMessageParameters 
                            { 
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438025" }, 
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 },
                                new ProcessMessageParameter { Name = "CGTS138", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS138) }
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.GEN.438025

        #region VR.ATO.GEN.438026

        /*  VR.ATO.GEN.438026
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Foreign resident CGT exemption (Division 855)", then Capital gains disregarded by a foreign resident amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "E - Foreign resident CGT exemption") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS140] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS140 = CGTS:RP:Capital.Gains.ForeignResidentExemption.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438026()
        {
            if (!ChildDocument.CGTS140.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(E - Foreign resident CGT exemption)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.GEN.438026",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Capital gains disregarded by a foreign resident amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Foreign resident CGT exemption (Division 855)"", then Capital gains disregarded by a foreign resident amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index + 1}]",
                            Parameters = new ProcessMessageParameters 
                            {
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438026" }, 
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 } ,
                                new ProcessMessageParameter { Name = "CGTS140", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS140) }
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.GEN.438026

        #region VR.ATO.GEN.438027

        /*  VR.ATO.GEN.438027
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Scrip for scrip roll-over (Subdivision 124-M)", then Capital gains disregarded as a result of a scrip for scrip roll-over amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "F - Scrip for scrip roll-over") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS45] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF  
     
        Data Elements:

        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS45 = CGTS:RP:Capital.Gains.ScriptForScriptRolloverDeferral.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438027()
        {
            if (!ChildDocument.CGTS45.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(F - Scrip for scrip roll-over)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.GEN.438027",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Capital gains disregarded as a result of a scrip for scrip roll-over amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Scrip for scrip roll-over (Subdivision 124-M)"", then Capital gains disregarded as a result of a scrip for scrip roll-over amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index - 1}]",
                            Parameters = new ProcessMessageParameters
                            { 
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438027" },
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 } ,
                                new ProcessMessageParameter { Name = "CGTS45", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS45) }
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.GEN.438027

        #region VR.ATO.GEN.438028

        /*  VR.ATO.GEN.438028
        If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is "Demerger exemption (Subdivision 125-C)", then Capital gains disregarded by a demerging entity amount on attached CGT schedule must be completed

        Legacy Rule Format:
        IF (RP:rvctc3.xx.xx:CapitalGainsTax.ExemptionOrRolloverApplied.Code = "H - Demerger exemption") AND (COUNT(SCHEDULE = "CGTS") = 1) AND [CGTS47] = NULL
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR330 = CTR:RP:CapitalGainsTax.ExemptionOrRolloverApplied.Code
        ^CGTS47 = CGTS:RP:Capital.Gains.DemergingEntityExemption.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438028()
        {
            if (!ChildDocument.CGTS47.HasValue && ParentDocument.CTR330Collection != null)
                Response.AddRange(ParentDocument.CTR330Collection.Select((s, i) => new { ctr330 = s, Index = i })
                    .Where(c => IsMatch(c.ctr330, "^(H - Demerger exemption)$", RegexOptions.IgnoreCase)).Select(c =>
                        new ProcessMessageDocument
                        {
                            Code = "CMN.ATO.GEN.438028",
                            Severity = ProcessMessageSeverity.Error,
                            Description = @"Capital gains disregarded by a demerging entity amount missing from CGT schedule",
                            LongDescription = @"If taxpayer is required to lodge a CGT schedule and CGT exemption or rollover applied code is ""Demerger exemption (Subdivision 125-C)"", then Capital gains disregarded by a demerging entity amount on attached CGT schedule must be completed",
                            Location = c.Index == 0 ? "/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code" : $"/xbrli:xbrl/tns:CapitalGainsTax.ExemptionOrRolloverApplied.Code[{c.Index - 1}]",
                            Parameters = new ProcessMessageParameters
                            {
                                new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438028" },
                                new ProcessMessageParameter { Name = "CTR330", Value = c.ctr330 } ,
                                new ProcessMessageParameter { Name = "CGTS47", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS47) }
                            },
                            DocumentSequence = "parent_doc"
                        }
                    ));
        }

        #endregion // VR.ATO.GEN.438028

        #region VR.ATO.CGTS.402173

        /*  VR.ATO.CGTS.402173
        Where the type of company is a life insurance company, friendly society or FHSA trust, the available discount on capital gains is 33%

        Legacy Rule Format:
        IF PARENT RETURN = "CTR" AND ([CTR49] <> SET ("63100","62400")) AND [CGTS126] > ((([CGTS118] - [CGTS123]) *0.33) +1)
           RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR49 = CTR:RP:OrganisationDetails.OrganisationIndustry2006Extended.Code
        ^CGTS126 = CGTS:RPApplied:TaxConcession.CapitalGains.DiscountTotal.Amount
        ^CGTS118 = CGTS:RP:Capital.Gains.Total.Amount
        ^CGTS123 = CGTS:RPApplied:Capital.Losses.Total.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402173()
        {
            ProcessMessageDocument processMessage;
            bool assertion = !IsMatch(ParentDocument.CTR49, @"^(63100|62400)$", RegexOptions.IgnoreCase) &&
                  ChildDocument.CGTS126.GetValueOrDefault() > (ChildDocument.CGTS118.GetValueOrDefault() - ChildDocument.CGTS123.GetValueOrDefault()) * 0.33M + 1;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument()
                {
                    Code = "CMN.ATO.CGTS.402173",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"The total percentage applied to capital gains by a company must not be greater than 33%",
                    LongDescription = @"The available discount on capital gains is 33% for life insurance companies, friendly societies and FHSA trusts",
                    Location = "/xbrli:xbrl/tns:TaxConcession.CapitalGains.DiscountTotal.Amount",
                    Parameters = new ProcessMessageParameters() { new ProcessMessageParameter() { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402173" } },
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR49", Value = ParentDocument.CTR49 });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS126", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS126) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS118", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS118) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS123", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS123) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGTS.402173

        #region VR.ATO.CGTS.402174

        /* VR.ATO.CGTS.402174
        The CGT discount rate available to trusts and companies is 50%.

        Legacy Rule Format:
        IF PARENT RETURN = SET("TRT", "CTR","TRTAMI") AND  [CGTS126] > ((([CGTS118] - [CGTS123]) *0.5) +1)
        RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
     
        ^CGTS126 = CGTS:RPApplied:TaxConcession.CapitalGains.DiscountTotal.Amount
        ^CGTS118 = CGTS:RP:Capital.Gains.Total.Amount
        ^CGTS123 = CGTS:RPApplied:Capital.Losses.Total.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402174()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ChildDocument.CGTS126.GetValueOrDefault() >
                             (ChildDocument.CGTS118.GetValueOrDefault() - ChildDocument.CGTS123.GetValueOrDefault()) * 0.50M + 1;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402174",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"The CGT discount rate applied to capital gains by a trust or company must not be greater than 50%",
                    Location = "/xbrli:xbrl/tns:TaxConcession.CapitalGains.DiscountTotal.Amount",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402174" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS126", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS126) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS118", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS118) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS123", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS123) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGTS.402174

        #region VR.ATO.CGTS.402203

        /* VR.ATO.CGTS.402203
        A capital loss must not be carried forward when a positive net capital gain amount has been provided  

        Legacy Rule Format:
        IF ([CTR53] <> "1") AND ([CGTS131] >0) AND ([CGTS125] > 0) 
        RETURN VALIDATION MESSAGE 
        ENDIF

        Data Elements:

        ^CTR53 = CTR:RP:OrganisationDetails.TaxConsolidationStatus.Code
        ^CGTS131 = CGTS:RP:Income.CapitalGainsNet.Amount
        ^CGTS125 = CGTS:RP.CGTOther.Unapplied:Capital.Losses.CarriedForward.Net.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402203()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR53 != "1" && (ChildDocument.CGTS131.GetValueOrDefault() > 0) &&
                             ChildDocument.CGTS125.GetValueOrDefault() > 0;
            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402203",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"A capital loss must not be carried forward when a positive net capital gain amount has been provided",
                    Location = "/xbrli:xbrl/tns:Capital.Losses.CarriedForward.Net.Amount",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402203" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR53", Value = ParentDocument.CTR53 });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS131", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS131) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS125", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS125) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGTS.402203

        #region VR.ATO.CGTS.402226

        /*  VR.ATO.CGTS.402226
        If the Amendment indicator on a parent return is set to TRUE, then the Income year earnout right created and Amount to be amended cannot be supplied.

        Legacy Rule Format:
        IF (PARENT RETURN:RP:pyin.xx.xx:Report.Amendment.Indicator = TRUE) AND ([CGTS150] <> NULL AND [CGTS151] <> NULL)
        RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR298 = CGTS:RP:Report.Amendment.Indicator
        ^CGTS150 = CGTS:RP:Report.TargetFinancial.Year
        ^CGTS151 = CGTS:RP:Miscellaneous.RequestedAmendment.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402226()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ParentDocument.CTR298.GetValueOrDefault() && ChildDocument.CGTS150.HasValue && ChildDocument.CGTS151.HasValue;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402226",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Income year earnout right created and Amount to be amended cannot be supplied when Parent return Amendment indicator is present.",
                    Location = "/xbrli:xbrl/tns:Report.TargetFinancial.Year",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402226" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR298", Value = CTR2026Validator.GetValueOrEmpty(ParentDocument.CTR298) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS150", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS150) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS151", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS151) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGTS.402226 

        #region VR.ATO.CGTS.402230

        /*  VR.ATO.CGTS.402230
        A multi-class treatment can only be reported with a Trust Tax Return for Attribution Managed Investments (TRTAMI) when a multi-class election has been made

        Legacy Rule Format:
        IF PARENT RETURN  <> "TRTAMI" AND ([CGTS153] <> NULL OR [CGTS154] <> NULL OR [CGTS155] <> NULL)
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CGTS153 = CGTS:RP:IncomeTax.AttributionManagedInvestmentTrustClass.Description
        ^CGTS154 = CGTS:RP:RPTransfersToOtherClasses:tns:Capital.Gains.Total.Amount
        ^CGTS155 = CGTS:RP:RPTransfersToOtherClasses:tns:Capital.Losses.Total.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402230()
        {
            ProcessMessageDocument processMessage;
            bool assertion = !string.IsNullOrEmpty(ChildDocument.CGTS153) || ChildDocument.CGTS154.HasValue || ChildDocument.CGTS155.HasValue;

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402230",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Multi-class treatment fields incorrectly supplied",
                    Location = "/xbrli:xbrl/tns:IncomeTax.AttributionManagedInvestmentTrustClass.Description",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402230" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS153", Value = ChildDocument.CGTS153 });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS154", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS154) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS155", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS155) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGTS.402230

        #region VR.ATO.CGTS.402240

        /* VR.ATO.CGTS.402240
        The year entered at Income year earnout right created cannot be the current year.

        Legacy Rule Format:
        IF([CGTS150] <> NULL) AND([CGTS150] = (PARENT RETURN:RP:pyin.xx.xx:Report.TargetFinancial.Year))
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CGTS150 = CGTS:RP:Report.TargetFinancial.Year
        ^CTR2 = CTR:RP:Report.TargetFinancial.Year
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402240()
        {
            ProcessMessageDocument processMessage;
            bool assertion = ChildDocument.CGTS150.HasValue && (ChildDocument.CGTS150.GetValueOrDefault() == ParentDocument.CTR2.GetValueOrDefault());

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402240",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Income year earnout right created incorrect",
                    Location = "/xbrli:xbrl/tns:Report.TargetFinancial.Year",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402240" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS150", Value = CTR2026Validator.GetValueOrEmpty(ChildDocument.CGTS150) });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR2", Value = CTR2026Validator.GetValueOrEmpty(ParentDocument.CTR2) });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.CGTS.402240

        #region VR.ATO.GEN.402009

        /* VR.ATO.GEN.402009
        Your supplied TFN does not match the TFN supplied on the form it was submitted with

        Legacy Rule Format:
        IF (RP:entity.identifier.TFN <> PARENT RETURN:RP:entity.identifier.TFN)
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR TFN = CTR:RP:entity.identifier.TFN
        ^CGTS TFN = CGTS:RP:entity.identifier.TFN
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN402009()
        {
            ProcessMessageDocument processMessage;
            bool assertion = !ParentDocument.RPIdentifierTFN.Equals(ChildDocument.RPIdentifierTFN);

            if (assertion)
            {
                processMessage = new ProcessMessageDocument
                {
                    Code = "CMN.ATO.GEN.402009",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Your supplied TFN does not match the TFN supplied on the form it was submitted with",
                    LongDescription = @"Your supplied TFN does not match the TFN supplied on the parent form it was submitted with",
                    Location = "/xbrli:xbrl/xbrli:context/xbrli:entity/xbrli:identifier",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.402009" } }
                };

                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CTR TFN", Value = ParentDocument.RPIdentifierTFN });
                processMessage.Parameters.Add(new ProcessMessageParameter { Name = "CGTS TFN", Value = ChildDocument.RPIdentifierTFN });
                Response.Add(processMessage);
            }
        }

        #endregion // VR.ATO.GEN.402009

        #region VR.ATO.GEN.438000

        /*  VR.ATO.GEN.438000
        Period start date within context on schedule doesn't match start date within PARENT RETURN:reporting party context

        Legacy Rule Format:
        IF (period.startDate WHERE CONTEXT(ALL)) <> PARENT RETURN:RP:period.startDate
           RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:
        
        ^CTR Start Date = CTR Start Date
        ^CGTS Start Date = CGTS Start Date
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438000()
        {
            Response.AddRange(from context in Contexts
                              where context.StartDate.GetValueOrDefault() != ParentDocument.RPStartDate.GetValueOrDefault()
                              select new ProcessMessageDocument
                              {
                                  Code = "CMN.ATO.GEN.438000",
                                  Severity = ProcessMessageSeverity.Error,
                                  Description = @"The context period start date is incorrect.",
                                  LongDescription = @"Period start date within context on the schedule must match period start date within the parent return reporting party context",
                                  Location = $"/xbrli:xbrl/xbrli:context[{context.Index}]/xbrli:period/xbrli:startDate",
                                  Parameters = new ProcessMessageParameters
                                  {
                                      new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438000" },
                                      new ProcessMessageParameter { Name = "CTR Start Date", Value = CTR2026Validator.GetValueOrEmptyDate(ParentDocument.RPStartDate) },
                                      new ProcessMessageParameter { Name = "CGTS Start Date", Value = CTR2026Validator.GetValueOrEmptyDate(context.StartDate) }
                                  }
                              });
        }

        #endregion // VR.ATO.GEN.438000

        #region VR.ATO.GEN.438001

        /*  VR.ATO.GEN.438001
        Period end date within context on schedule doesn't match end date within PARENT RETURN:reporting party context

        Legacy Rule Format:
        IF (period.endDate WHERE CONTEXT(ALL)) <> PARENT RETURN:RP:period.endDate
           RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CTR End Date = CTR End Date
        ^CGTS End Date = CGTS End Date
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438001()
        {
            Response.AddRange(from context in Contexts
                              where context.EndDate.GetValueOrDefault() != ParentDocument.RPEndDate.GetValueOrDefault()
                              select new ProcessMessageDocument
                              {
                                  Code = "CMN.ATO.GEN.438001",
                                  Severity = ProcessMessageSeverity.Error,
                                  Description = @"The context period end date is incorrect.",
                                  LongDescription = @"Period end date within context on the schedule must match period end date within the parent return reporting party context",
                                  Location = $"/xbrli:xbrl/xbrli:context[{context.Index}]/xbrli:period/xbrli:endDate",
                                  Parameters = new ProcessMessageParameters
                                  {
                                      new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438001" },
                                      new ProcessMessageParameter { Name = "CTR End Date", Value = CTR2026Validator.GetValueOrEmptyDate(ParentDocument.RPEndDate) },
                                      new ProcessMessageParameter { Name = "CGLS End Date", Value = CTR2026Validator.GetValueOrEmptyDate(context.EndDate) }
                                  }
                              });
        }

        #endregion // VR.ATO.GEN.438001

        private static bool IsMatch(string field, string expression, RegexOptions options = RegexOptions.None)
            => field != null && Regex.IsMatch(field, expression, options);
    }
}