using Ato.CD.Inbound.Shared;
using Ato.CD.Inbound.Shared201802;
using Ato.EN.IntegrationServices.CodeGenerationCGTS;
using Ato.EN.IntegrationServices.CodeGenerationTRTAMI;
using DataContracts;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Ato.CD.Inbound.TRTAMI202602
{
    public class CrossFormValidatorCGTS : ICrossFormValidator
    {
        private CGTS2018 ChildDocument { get; set; }

        private List<Context> Contexts { get; set; }

        public List<ProcessMessageDocument> Response { get; private set; }

        private TRTAMI2026 ParentDocument { get; set; }

        public CrossFormValidatorCGTS(TRTAMI2026 parent, object child)
        {
            ChildDocument = (CGTS2018)child;
            Contexts = ChildDocument.GetContexts();
            ParentDocument = parent;
            Response = new List<ProcessMessageDocument>();
        }

        public List<ProcessMessageDocument> ValidateCrossFormRules()
        {        
            VRATOCGTS402165();
            VRATOCGTS402171();
            VRATOCGTS402174();
            VRATOCGTS402226();
            VRATOCGTS402240();
            VRATOGEN402009();
            VRATOGEN438000();
            VRATOGEN438001();

            return Response;
        }

        #region Validation Rules

        #region VR.ATO.CGTS.402165

        /*  VR.ATO.CGTS.402165
        Total losses transferred in applied is only valid for a company

        Legacy Rule Format:
        IF (PARENT RETURN <> "CTR") AND ([CGTS122] <> NULL)  
            RETURN VALIDATION MESSAGE
        ENDIF

        Data Elements:

        ^CGTS122 = CGTS:RPApplied:Capital.Losses.TransferredTotal.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402165()
        {
            bool assertion = ChildDocument.CGTS122.HasValue;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402165",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Total losses transferred in applied is only valid for a company",
                    Location = "/xbrli:xbrl/tns:Capital.Losses.TransferredTotal.Amount",
                    Parameters = new ProcessMessageParameters {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.CGTS.402165" },
                        new ProcessMessageParameter { Name = "CGTS122", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS122) }
                    }
                });
            }
        }

        #endregion // VR.ATO.CGTS.402165

        #region VR.ATO.CGTS.402171

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

        Legacy Rule Format:
        IF PARENT RETURN = SET("SMSFAR","FITR","TRT","TRTAMI") AND ([CGTS131] > 0) AND ([CGTS125]  > 0) 
            RETURN VALIDATION MESSAGE 
        ENDIF

        Data Elements:

        ^CGTS125 = CGTS:RPCGTOtherUnappliedInstant:Capital.Losses.CarriedForward.Net.Amount

        ^CGTS131 = CGTS:RP:Income.CapitalGainsNet.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402171()
        {
            bool assertion = ChildDocument.CGTS131.GetValueOrDefault() > 0 && ChildDocument.CGTS125.GetValueOrDefault() > 0;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.CGTS.402171",
                    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.402171" },
                        new ProcessMessageParameter { Name = "CGTS125", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS125) },
                        new ProcessMessageParameter { Name = "CGTS131", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS131) }
                    }
                });
            }
        }

        #endregion // VR.ATO.CGTS.402171

        #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:

        ^CGTS118 = CGTS:RP:Capital.Gains.Total.Amount

        ^CGTS123 = CGTS:RPApplied:Capital.Losses.Total.Amount

        ^CGTS126 = CGTS:RPApplied:TaxConcession.CapitalGains.DiscountTotal.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402174()
        {
            bool assertion = ChildDocument.CGTS126.GetValueOrDefault() > (((ChildDocument.CGTS118.GetValueOrDefault() - ChildDocument.CGTS123.GetValueOrDefault()) * 0.5m) + 1);

            if (assertion)
            {
                Response.Add(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" },
                        new ProcessMessageParameter { Name = "CGTS118", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS118) },
                        new ProcessMessageParameter { Name = "CGTS123", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS123) },
                        new ProcessMessageParameter { Name = "CGTS126", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS126) }
                    }
                });
            }
        }

        #endregion // VR.ATO.CGTS.402174

        #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:

        ^TRTAMI6 = TRTAMI:RP:ReportAmendmentDetails:Report.Amendment.Indicator

        ^CGTS150 = CGTS:RP:Report.TargetFinancial.Year

        ^CGTS151 = CGTS:RP:Miscellaneous.RequestedAmendment.Amount
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOCGTS402226()
        {
            bool assertion = ParentDocument.TRTAMI6.GetValueOrDefault() && (ChildDocument.CGTS150.HasValue && ChildDocument.CGTS151.HasValue);

            if (assertion)
            {
                Response.Add(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" },
                        new ProcessMessageParameter { Name = "TRTAMI6", Value = TRTAMI2026Validator.GetValueOrEmpty(ParentDocument.TRTAMI6) },
                        new ProcessMessageParameter { Name = "CGTS150", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS150) },
                        new ProcessMessageParameter { Name = "CGTS151", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS151) }
                    }
                });
            }
        }

        #endregion // VR.ATO.CGTS.402226

        #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:

        ^TRTAMI1 = TRTAMI:RP:Report.TargetFinancial.Year

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

            if (assertion)
            {
                Response.Add(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" },
                        new ProcessMessageParameter { Name = "TRTAMI1", Value = TRTAMI2026Validator.GetValueOrEmpty(ParentDocument.TRTAMI1) },
                        new ProcessMessageParameter { Name = "CGTS150", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.CGTS150) }
                    }
                });
            }
        }

        #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:

        ^TRTAMI4 = TRTAMI:RP:Identifiers.TaxFileNumber.Identifier

        ^CGTS TFN = CGTS TFN
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN402009()
        {
            bool assertion = !ParentDocument.TRTAMI4.Equals(ChildDocument.RPIdentifierTFN);

            if (assertion)
            {
                Response.Add(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" },
                        new ProcessMessageParameter { Name = "TRTAMI4", Value = TRTAMI2026Validator.GetValueOrEmpty(ParentDocument.TRTAMI4) },
                        new ProcessMessageParameter { Name = "CGTS TFN", Value = TRTAMI2026Validator.GetValueOrEmpty(ChildDocument.RPIdentifierTFN) }
                    }
                });
            }
        }

        #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:

        ^TRTAMI2 = TRTAMI:RP:Period.Start.Date

        ^CGTS Context Start Date = CGTS Context Start Date
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438000()
        {
            Response.AddRange(from context in Contexts
                              where context.StartDate.GetValueOrDefault() != ParentDocument.TRTAMI2.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.Id}]/xbrli:period/xbrli:startDate",
                                  Parameters = new ProcessMessageParameters {
                                      new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438000" },
                                      new ProcessMessageParameter { Name = "TRTAMI2", Value = TRTAMI2026Validator.GetValueOrEmptyDate(ParentDocument.TRTAMI2) },
                                      new ProcessMessageParameter { Name = "Context Start Date", Value = TRTAMI2026Validator.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:

        ^TRTAMI3 = TRTAMI:RP:Period.End.Date

        ^CGTS Context End Date = CGTS Context End Date
        */
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void VRATOGEN438001()
        {
            Response.AddRange(from context in Contexts
                              where context.EndDate.GetValueOrDefault() != ParentDocument.TRTAMI3.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.Id}]/xbrli:period/xbrli:endDate",
                                  Parameters = new ProcessMessageParameters {
                                      new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.GEN.438001" },
                                      new ProcessMessageParameter { Name = "TRTAMI3", Value = TRTAMI2026Validator.GetValueOrEmptyDate(ParentDocument.TRTAMI3) },
                                      new ProcessMessageParameter { Name = "Context End Date", Value = TRTAMI2026Validator.GetValueOrEmptyDate(context.EndDate) }
                                  }
                              });
        }

        #endregion // VR.ATO.GEN.438001

        #endregion
    }
}
