using Ato.CD.Inbound.Shared;
using Ato.EN.IntegrationServices.CodeGenerationIDS;
using Ato.EN.IntegrationServices.CodeGenerationPTR;
using DataContracts;
using System.Collections.Generic;
using System.Linq;
using VaTS;
using static Ato.CD.Inbound.Shared.ValidatorHelpers;

namespace Ato.CD.Inbound.PTR202602
{
    public class CrossFormValidatorIDS : ICrossFormValidator
    {
        private PTR2025 ParentDocument { get; }

        private IDS2025 ChildDocument { get; }

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

        public CrossFormValidatorIDS(PTR2025 report, BusinessDocument childDocument)
        {
            ParentDocument = report;
            ChildDocument = (IDS2025)childDocument.ConsumedReport;
            Response = new List<ProcessMessageDocument>();
        }

        public List<ProcessMessageDocument> ValidateCrossFormRules()
        {
            VRATOIDS440670();  // existing
            VRATOPTR438082();
            VRATOPTR431002();
            VRATOPTR431045();
            VRATOPTR430999();
            VRATOPTR430998();
            VRATOPTR431003();
            VRATOPTR431001();
            VRATOPTR432000();
            VRATOPTR430996();
            VRATOPTR430995();

            return Response;
        }

        #region VR.ATO.IDS.440670
        /* 
            Rule ID: VR.ATO.IDS.440670

            IF (RP:entity.identifier.TFN <> PARENT RETURN:RP:entity.identifier.TFN)
                RETURN VALIDATION MESSAGE
            ENDIF
        */
        public void VRATOIDS440670()
        {
            bool assertion = !ParentDocument.PTR5.Equals(ChildDocument.IDS500);

            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.IDS.440670" } }
                });
            }
        }
        #endregion VR.ATO.IDS.440670

        #region VR.ATO.PTR.438082
        /*
            VR.ATO.PTR.438082

            If the entity has self-assessed as a Significant Global Entity (SGE), then 'Are you a small business entity, 
            not a significant global entity and your international related party dealings do not exceed $5 million and 50% of your current year aggregated turnover?' 
            must not be 'TRUE' on the International Dealings Schedule (IDS) form.

            Technical Business Rule Format:
            ^PTR355 = TRUE AND CountDocument('IDS') = 1 AND ^IDS425 = TRUE

            Data Elements:
            ^PTR355 = PTR:RP:OrganisationDetailsSignificantGlobalEntityStatusI
            ^IDS425 = IDS425

        */

        public void VRATOPTR438082()
        {
            bool assertion = ParentDocument.PTR355.GetValueOrDefault() && ChildDocument.IDS425.GetValueOrDefault();

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.438082",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Significant Global Entity question on the International Dealings Schedule (IDS) form must not be 'TRUE'.",
                    Location = "/tns:PTR/tns:RP/tns:OrganisationDetailsSignificantGlobalEntityStatusI",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.438082" },
                        new ProcessMessageParameter { Name = "PTR355", Value = ParentDocument.PTR355.GetValueOrDefault().ToString() },
                        new ProcessMessageParameter { Name = "IDS425", Value = ChildDocument.IDS425.GetValueOrDefault().ToString()},
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.438082

        #region VR.ATO.PTR.431002

        /*
            VR.ATO.PTR.431002

            If Debt deductions in earning non-assessable foreign income claimed under s25-90 has been completed on the IDS then 
            Total interest expenses or Interest expenses overseas must be greater than zero on the partnership form.

            Technical Business Rule Format:
            (^PTR346 = NULL OR ^PTR346 = 0) AND CountOccurrence(^PTR96, ^PTR96 <> NULL) = 0 AND 
            (^PTR137 = NULL OR ^PTR137 = 0) AND CountDocument('IDS') = 1 AND ^IDS207 > 0

            Data Elements:
            ^PTR346 = PTR:RP:Income:BusinessIncomeAndExpenses:BusinessExpenses:OperatingInterestA
            ^PTR96 =  PTR:RP:OtherDeductionsCollection:OtherDeductions:ExpenseDeductibleOtherA
            ^PTR137 = PTR:RP:OverseasTransactions:ExpenseInterestA
            ^IDS207 = IDS207
        */
        public void VRATOPTR431002()
        {
            int countPTR96 = ParentDocument.RP_OtherDeductionsCollection?.Count(othrd => othrd.PTR96.HasValue) ?? 0;

            bool assertion = ParentDocument.PTR346.GetValueOrDefault() == 0 && countPTR96 == 0 && ParentDocument.PTR137.GetValueOrDefault() == 0
                    && ChildDocument.IDS207.GetValueOrDefault() > 0;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.431002",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Interest expenses required",
                    LongDescription = @"If Debt deductions in earning non-assessable foreign income claimed under s25-90 has been completed on the IDS then Total interest expenses or Interest expenses overseas must be greater than zero on the partnership form.",
                    Location = "/tns:PTR/tns:RP/tns:Income/tns:BusinessIncomeAndExpenses/tns:BusinessExpenses/tns:OperatingInterestA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.431002" },
                        new ProcessMessageParameter { Name = "PTR346", Value =  GetValueOrEmpty(ParentDocument.PTR346)},
                        new ProcessMessageParameter { Name = "Count(PTR96)", Value = countPTR96.ToString()},
                        new ProcessMessageParameter { Name = "PTR137", Value =  GetValueOrEmpty(ParentDocument.PTR137)},
                        new ProcessMessageParameter { Name = "IDS207", Value = ChildDocument.IDS207.GetValueOrDefault().ToString()},
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.431002

        #region VR.ATO.PTR.431045
        /*
            VR.ATO.PTR.431045

            If there is a 'NO' response to the questions concerning whether the entity had either a direct or indirect interest in a foreign trust, 
            controlled foreign company or transferor trust and whether the value of dealings with international related parties is greater than $2 million and whether 
            the thin capitalisation or debt deduction creation rules apply, and no amounts have been completed at Interest expenses overseas and Royalty expenses overseas, 
            an International Dealings Schedule must not be attached.

            Technical Business Rule Format:
            ^PTR102 = FALSE AND ^PTR108 = FALSE AND ^PTR277 = FALSE AND (^PTR137 = NULL OR ^PTR137 = 0) AND (^PTR138 = NULL OR ^PTR138 = 0) AND CountDocument('IDS') = 1

            Data Elements:
            ^PTR102 = PTR:RP:AttributedForeignIncome:InternationalDealingsTrustorControlledCompanyorTransferorTrustI
            ^PTR108 = PTR:RP:OverseasTransactions:InternationalDealingsRelatedPartiesTransactionsExcessAggregateValueI
            ^PTR277 = PTR:RP:OverseasTransactions:LiabilitiesThinCapitalisationProvisionsAppliedI
            ^PTR137 = PTR:RP:OverseasTransactions:ExpenseInterestA
            ^PTR138 = PTR:RP:OverseasTransactions:ExpenseRoyaltiesA
        */

        public void VRATOPTR431045()
        {
            bool assertion = !ParentDocument.PTR102.GetValueOrDefault() && !ParentDocument.PTR108.GetValueOrDefault() && !ParentDocument.PTR277.GetValueOrDefault() &&
                ParentDocument.PTR137.GetValueOrDefault() == 0 && ParentDocument.PTR138.GetValueOrDefault() == 0;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.431045",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"International Dealings Schedule is not required",
                    LongDescription = @"If there is a 'NO' response to the questions concerning whether the entity had either a direct or indirect interest in a foreign trust, controlled foreign company or transferor trust and whether the value of dealings with international related parties is greater than $2 million and whether the thin capitalisation or debt deduction creation rules apply, and no amounts have been completed at Interest expenses overseas and Royalty expenses overseas, an International Dealings Schedule must not be attached.",
                    Location = "/tns:PTR/tns:RP/tns:Income/tns:BusinessIncomeAndExpenses/tns:IncomePrimaryProduction/tns:RemunerationABNNotQuotedPaymentGrossA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.431045" },
                        new ProcessMessageParameter { Name = "PTR102", Value = GetValueOrEmpty(ParentDocument.PTR102)},
                        new ProcessMessageParameter { Name = "PTR108", Value = GetValueOrEmpty(ParentDocument.PTR108)},
                        new ProcessMessageParameter { Name = "PTR277", Value = GetValueOrEmpty(ParentDocument.PTR277)},
                        new ProcessMessageParameter { Name = "PTR137", Value = GetValueOrEmpty(ParentDocument.PTR137)},
                        new ProcessMessageParameter { Name = "PTR138", Value = GetValueOrEmpty(ParentDocument.PTR138)},
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.431045

        #region VR.ATO.PTR.430999
        /*
            VR.ATO.PTR.430999

            The amount showing at section 456 –attributable income controlled foreign companies on the IDS should be equal to or less than the amount at Listed country.

            Technical Business Rule Format:
            ^PTR98 > 0 AND CountDocument('IDS') = 1 AND ^IDS188 > ^PTR98

            Data Elements:
            ^PTR98 = PTR:RP:AttributedForeignIncome:ListedCountryInternationalDealingsA
            ^IDS188
        */

        public void VRATOPTR430999()
        {
            bool assertion = ParentDocument.PTR98.GetValueOrDefault() > 0 && ChildDocument.IDS188.GetValueOrDefault() > ParentDocument.PTR98.GetValueOrDefault();

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.430999",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Attributed foreign income incorrect",
                    LongDescription = @"Assessable income of controlled foreign companies and controlled foreign trusts under section 456 for Listed countries on the IDS should be equal to or less than Attributed foreign income - Listed country on the partnership return.",
                    Location = "/tns:PTR/tns:RP/tns:AttributedForeignIncome/tns:ListedCountryInternationalDealingsA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.430999" },
                        new ProcessMessageParameter { Name = "PTR98", Value =  GetValueOrEmpty(ParentDocument.PTR98)},
                        new ProcessMessageParameter { Name = "IDS188", Value = GetValueOrEmpty(ChildDocument.IDS188)},
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.430999

        #region VR.ATO.PTR.430998
        /*
            VR.ATO.PTR.430998

            The sum of the amounts showing at attributable income of controlled foreign companies and controlled foreign trusts on the IDS should be equal to or less than 
            the sum of the amounts at Listed country and Unlisted country on the main return form.

            Technical Business Rule Format:
            (^PTR100 > 0 OR ^PTR98 > 0) AND CountDocument('IDS') = 1 AND (^PTR98 + ^PTR100) < (^IDS191 + ^IDS192 + ^IDS193)

            Data Elements:
            ^PTR100 = PTR:RP:AttributedForeignIncome:UnlistedCountryInternationalDealingsA
            ^PTR98  = PTR:RP:AttributedForeignIncome:ListedCountryInternationalDealingsA
            ^IDS191
            ^IDS192
            ^IDS193
        */

        public void VRATOPTR430998()
        {
            bool assertion = (ParentDocument.PTR100.GetValueOrDefault() > 0 || ParentDocument.PTR98.GetValueOrDefault() > 0) &&
                ((ParentDocument.PTR98.GetValueOrDefault() + ParentDocument.PTR100.GetValueOrDefault()) <
                 (ChildDocument.IDS191.GetValueOrDefault() + ChildDocument.IDS192.GetValueOrDefault() + ChildDocument.IDS193.GetValueOrDefault()));

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.430998",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Attributed foreign income incorrect",
                    LongDescription = @"The sum of amounts at attributable income of controlled foreign companies and controlled foreign trusts on the IDS should be equal to or less than the sum of amounts at Listed country and Unlisted country on the partnership return form.",
                    Location = "/tns:PTR/tns:RP/tns:AttributedForeignIncome/tns:UnlistedCountryInternationalDealingsA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.430998" },
                        new ProcessMessageParameter { Name = "PTR100", Value = GetValueOrEmpty(ParentDocument.PTR100)},
                        new ProcessMessageParameter { Name = "PTR98",  Value = GetValueOrEmpty(ParentDocument.PTR98)},
                        new ProcessMessageParameter { Name = "IDS191", Value = GetValueOrEmpty(ChildDocument.IDS191)},
                        new ProcessMessageParameter { Name = "IDS192", Value = GetValueOrEmpty(ChildDocument.IDS192)},
                        new ProcessMessageParameter { Name = "IDS193", Value = GetValueOrEmpty(ChildDocument.IDS193)},
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.430998

        #region VR.ATO.PTR.431003
        /*
            VR.ATO.PTR.431003

            An amount is showing at Total amount of your share of net income/distribution of profit (on  the IDS) and there is no amount at Gross other assessable foreign source income

            Technical Business Rule Format:
            ^PTR104 = NULL AND CountDocument('IDS') = 1 AND ^IDS219 > 0

            Data Elements:
            ^PTR104 = PTR:RP:OtherAssessableForeignSourceIncome:A
            ^IDS219
        */

        public void VRATOPTR431003()
        {
            bool assertion = !ParentDocument.PTR104.HasValue && ChildDocument.IDS219.GetValueOrDefault() > 0;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.431003",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Gross other assessable foreign source income required",
                    LongDescription = @"If Total amount of your share of net income/distribution of profit has been completed on the IDS then the Gross Other assessable foreign source income must be completed on the partnership return form.",
                    Location = "/tns:PTR/tns:RP/tns:OtherAssessableForeignSourceIncome/tns:A",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.431003" },
                        new ProcessMessageParameter { Name = "PTR104", Value = GetValueOrEmpty(ParentDocument.PTR104)},
                        new ProcessMessageParameter { Name = "IDS219", Value = GetValueOrEmpty(ChildDocument.IDS219)},
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.431003

        #region VR.ATO.PTR.431001

        /*  
            VR.ATO.PTR.431001
            Transactions with specified countries question incorrect

            Legacy Rule Format:
            ^PTR109 = FALSE AND CountDocument('IDS') = 1 AND ^IDS9 = TRUE

            Technical Business Rule Format:
            ^PTR109 = FALSE AND CountDocument('IDS') = 1 AND ^IDS9 = TRUE

            Data Elements:

            ^PTR109 = PTR:RP:InternationalDealings.TransactionsWithTaxHavenCountries.Indicator
        */
        public void VRATOPTR431001()
        {
            bool assertion = !ParentDocument.PTR109.GetValueOrDefault() && ChildDocument.IDS9.GetValueOrDefault();

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.431001",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Transactions with specified countries question incorrect",
                    LongDescription = @"If there is a 'True' response at 'Did you have dealings with international related parties located in specified countries?' on the IDS then the response at Overseas transactions - Transactions with specified countries on the partnership return must be 'True'.",
                    Location = "/tns:PTR/tns:RP/tns:InternationalDealingsTransactionsWithTaxHavenCountriesI",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.431001" },
                        new ProcessMessageParameter { Name = "PTR109", Value = ParentDocument.PTR109.GetValueOrDefault().ToString() },
                        new ProcessMessageParameter { Name = "IDS9", Value = ChildDocument.IDS9.ToString() },
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.431001

        #region VR.ATO.PTR.432000

        /*  
            VR.ATO.PTR.432000
            If there is an amount for Total TOFA losses or Total TOFA gains, then 'Are you subject to the Taxation of Financial Arrangements rules' must be true.

            Legacy Rule Format:
            (^PTR251 > 0 OR ^PTR252 > 0) AND CountDocument('IDS') = 1 AND ^IDS177 <> TRUE

            Technical Business Rule Format:
            (^PTR251 > 0 OR ^PTR252 > 0) AND CountDocument('IDS') = 1 AND ^IDS177 <> TRUE

            Data Elements:

            ^PTR251 = PTR:RP:TaxationOfFinancialArrangements.Income.GainsTotal.Amount
            ^PTR252 = PTR:RP:TaxationOfFinancialArrangements.Expense.LossesTotal.Amount
            
        */
        public void VRATOPTR432000()
        {
            bool assertion = (ParentDocument.PTR251 > 0 || ParentDocument.PTR252 > 0) && !ChildDocument.IDS177.GetValueOrDefault();

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.433000",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"If there is an amount for Total TOFA losses or Total TOFA gains, then 'Are you subject to the Taxation of Financial Arrangements rules' must be true.",
                    LongDescription = @"If there is an amount at either 'Total TOFA gains' or 'Total TOFA Losses' that indicates you made a gain or loss from a financial arrangement subject to the TOFA rules, then there must be a 'True' response to 'Are you subject to the Taxation of Financial Arrangements rules contained in Division 230 of the ITAA 1997?' on the IDS.",
                    Location = "/tns:PTR/tns:RP/tns:TaxationOfFinancialArrangements/tns:IncomeGainsTotalA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.432000" },
                        new ProcessMessageParameter { Name = "PTR251", Value = ParentDocument.PTR251.ToString() },
                        new ProcessMessageParameter { Name = "PTR251", Value = ParentDocument.PTR251.ToString() },
                        new ProcessMessageParameter { Name = "IDS177", Value = ChildDocument.IDS177.GetValueOrDefault().ToString() },
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.432000

        #region VR.ATO.PTR.430996

        /*  
            VR.ATO.PTR.430996
            Royalties deductions incorrect

            Legacy Rule Format:
            ^PTR138 > 0 AND CountDocument('IDS') = 1 AND ^PTR138 < ^IDS22

            Technical Business Rule Format:
            ^PTR138 > 0 AND CountDocument('IDS') = 1 AND ^PTR138 < ^IDS22

            Data Elements:

            ^PTR138 = PTR:RP:OverseasTransactions:Expense.Royalties.Amount			
            
        */
        public void VRATOPTR430996()
        {
            bool assertion = ParentDocument.PTR138 > 0 && ParentDocument.PTR138 < ChildDocument.IDS22;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.430996",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Royalties deductions incorrect",
                    LongDescription = @"If Royalties deductions has been completed on the IDS then it must be less than or equal to Royalty expenses overseas on the partnership return form.",
                    Location = "/tns:PTR/tns:RP/tns:OverseasTransactions/tns:ExpenseRoyaltiesA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.430996" },
                        new ProcessMessageParameter { Name = "PTR138", Value = ParentDocument.PTR138.ToString() },
                        new ProcessMessageParameter { Name = "IDS22", Value = ChildDocument.IDS22.ToString() },
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.430996

        #region VR.ATO.PTR.430995

        /*  
            VR.ATO.PTR.430995
            Royalty expenses overseas required

            Legacy Rule Format:
            (^PTR138 = 0 OR ^PTR138 = NULL) AND CountDocument('IDS') = 1 AND ^IDS22 > 0

            Technical Business Rule Format:
            (^PTR138 = 0 OR ^PTR138 = NULL) AND CountDocument('IDS') = 1 AND ^IDS22 > 0

            Data Elements:

            ^PTR138 = PTR:RP:OverseasTransactions:Expense.Royalties.Amount			
            
        */
        public void VRATOPTR430995()
        {
            bool assertion = (ParentDocument.PTR138 == 0 || ParentDocument.PTR138 == null) && ChildDocument.IDS22 > 0;

            if (assertion)
            {
                Response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.PTR.430995",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Royalty expenses overseas required",
                    LongDescription = @"If a Royalties deduction amount has been completed on the IDS then Royalty expenses overseas must be greater than zero on the partnership form.",
                    Location = "/tns:PTR/tns:RP/tns:OverseasTransactions/tns:ExpenseRoyaltiesA",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.PTR.430995" },
                        new ProcessMessageParameter { Name = "PTR138", Value = ParentDocument.PTR138.ToString() },
                        new ProcessMessageParameter { Name = "IDS22", Value = ChildDocument.IDS22.ToString() },
                    },
                    DocumentSequence = "parent_doc"
                });
            }
        }

        #endregion VR.ATO.PTR.430995

    }
}