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

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

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

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

        private TRTAMI2025 parentDocument { get; set; }

        public CrossFormValidatorCGTS(TRTAMI2025 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

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

        Data Elements:
            ^CGTS122 = CGTS122
        */
        public 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 = TRTAMI2025Validator.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

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

        Data Elements:
            ^CGTS125 = CGTS125

            ^CGTS131 = CGTS131
        */
        public 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 = TRTAMI2025Validator.GetValueOrEmpty(childDocument.CGTS125) },
                        new ProcessMessageParameter { Name = "CGTS131", Value = TRTAMI2025Validator.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

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

        Data Elements:
            ^CGTS118 = CGTS118

            ^CGTS123 = CGTS123

            ^CGTS126 = CGTS126
        */
        public 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 = TRTAMI2025Validator.GetValueOrEmpty(childDocument.CGTS118) },
                        new ProcessMessageParameter { Name = "CGTS123", Value = TRTAMI2025Validator.GetValueOrEmpty(childDocument.CGTS123) },
                        new ProcessMessageParameter { Name = "CGTS126", Value = TRTAMI2025Validator.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

        Technical Business 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:
            ^CGTS150 = CGTS150

            ^CGTS151 = CGTS151
        */
        public 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 = TRTAMI2025Validator.GetValueOrEmpty(parentDocument.TRTAMI6) },
                        new ProcessMessageParameter { Name = "CGTS150", Value = TRTAMI2025Validator.GetValueOrEmpty(childDocument.CGTS150) },
                        new ProcessMessageParameter { Name = "CGTS151", Value = TRTAMI2025Validator.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
        
        Technical Business Rule Format:
            IF ([CGTS150] <> NULL) AND ([CGTS150] = (PARENT RETURN:RP:pyin.xx.xx:Report.TargetFinancial.Year))
              RETURN VALIDATION MESSAGE
            ENDIF

        Data Elements:
            ^CGTS150 = CGTS150
         */
        public 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 = TRTAMI2025Validator.GetValueOrEmpty(parentDocument.TRTAMI1) },
                        new ProcessMessageParameter { Name = "CGTS150", Value = TRTAMI2025Validator.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

        Technical Business Rule Format:
            IF (RP:entity.identifier.TFN <> PARENT RETURN:RP:entity.identifier.TFN)
              RETURN VALIDATION MESSAGE
            ENDIF
        */
        public 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 = TRTAMI2025Validator.GetValueOrEmpty(parentDocument.TRTAMI4) },
                        new ProcessMessageParameter { Name = "CGTSTFN", Value = TRTAMI2025Validator.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

        Technical Business Rule Format:
            IF (period.startDate WHERE CONTEXT(ALL)) <> PARENT RETURN:RP:period.startDate
              RETURN VALIDATION MESSAGE
            ENDIF
        */
        public 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 = TRTAMI2025Validator.GetValueOrEmptyDate(parentDocument.TRTAMI2) },
                                      new ProcessMessageParameter { Name = "ContextStartDate", Value = TRTAMI2025Validator.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

        Technical Business Rule Format:
            IF (period.endDate WHERE CONTEXT(ALL)) <> PARENT RETURN:RP:period.endDate
               RETURN VALIDATION MESSAGE
            ENDIF
        */
        public 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 = TRTAMI2025Validator.GetValueOrEmptyDate(parentDocument.TRTAMI3) },
                                      new ProcessMessageParameter { Name = "ContextEndDate", Value = TRTAMI2025Validator.GetValueOrEmptyDate(context.EndDate) }
                                  }
                              });
        }

        #endregion // VR.ATO.GEN.438001


        #endregion
    }
}