using Ato.CD.Inbound.Shared;
using Ato.EN.IntegrationServices.CodeGenerationFTER;
using Ato.EN.IntegrationServices.CodeGenerationSMSFAR;
using VaTS;
using DataContracts;
using System;
using System.Collections.Generic;

namespace Ato.CD.Inbound.SMSFAR
{
    internal class CrossFormValidatorFTER : ICrossFormValidator
    {
        private SMSFAR2026 ParentDocument { get; }

        private FTER2021 ChildDocument { get; }

        internal CrossFormValidatorFTER(SMSFAR2026 report, BusinessDocument childDocument)
        {
            ParentDocument = report;
            ChildDocument = (FTER2021)childDocument.ConsumedReport;
        }

        public List<ProcessMessageDocument> ValidateCrossFormRules()
        {
            var response = new List<ProcessMessageDocument>();
            
            VRATOFTER408001(response);
            VRATOFTER408029(response);
            VRATOFTER408033(response);
            VRATOFTER408112(response);
            VRATOFTER408162(response);
            VRATOFTER408205(response);
            VRATOFTER408371(response);
            VRATOFTER408372(response);

            return response;
        }

        #region VR.ATO.FTER.402805
        //IF (RP:pyid.xx.xx:Identifiers.AustralianBusinessNumber.Identifier <> NULLORBLANK)
        //    AND (PARENT RETURN:RP:pyid.xx.xx:Identifiers.AustralianBusinessNumber.Identifier <> NULLORBLANK)
        //    AND (RP:pyid.xx.xx:Identifiers.AustralianBusinessNumber.Identifier <> PARENT RETURN:RP:pyid.xx.xx:Identifiers.AustralianBusinessNumber.Identifier)
        //    RETURN VALIDATION MESSAGE
        //ENDIF
        private void VRATOFTER408205(List<ProcessMessageDocument> response)
        {
            bool assertion = !string.IsNullOrWhiteSpace(ParentDocument.SMSFAR5) &&
                             !string.IsNullOrWhiteSpace(ChildDocument.FTER170) &&
                             !ParentDocument.SMSFAR5.Equals(ChildDocument.FTER170);
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.GEN.402010",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Your supplied ABN does not match the ABN supplied on the form it was submitted with",
                    LongDescription = "Your supplied ABN does not match the ABN supplied on the parent form it was submitted with",
                    Location = "/tns:FTER/tns:RP/tns:AustralianBusinessNumberId",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.402805" } }
                });
            }
        }
        #endregion

        #region VR.ATO.FTER.408001
        //WHERE PARENT RETURN EXISTS 
        //IF(FTER:RP:entity.identifier.TFN<> NULLORBLANK) AND(FTER:RP:entity.identifier.TFN<> PARENT RETURN:RP:entity.identifier.TFN)
        //  RETURN VALIDATION MESSAGE
        //ENDIF
        private void VRATOFTER408001(List<ProcessMessageDocument> response)
        {
            bool assertion = !string.IsNullOrWhiteSpace(ChildDocument.FTER3) &&
                             !ParentDocument.RPIdentifierTFN.Equals(ChildDocument.FTER3);
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.GEN.410115",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "TFN on Schedule must match TFN on main form",
                    Location = "/tns:FTER/tns:RP/tns:TaxFileNumberId",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408001" } }
                });
            }
        }
        #endregion

        #region VR.ATO.FTER.408029
        //WHERE PARENT RETURN EXISTS
        //IF[FTER95] = "V" AND [FTER40] <> NULL AND[FTER40] <> PARENT RETURN:RP:pyin.xx.xx:Report.TargetFinancial.Year
        //    RETURN VALIDATION MESSAGE
        //ENDIF
        //[FTER95] = FTER:RP:Elections.FamilyTrustElectionRevocation.Code
        //[FTER40] = FTER:RP:Elections.FamilyTrustElectionStatus.Year
        private void VRATOFTER408029(List<ProcessMessageDocument> response)
        {
            bool assertion = !string.IsNullOrWhiteSpace(ChildDocument.FTER95) &&
                             ChildDocument.FTER95.ToUpper().Equals("V") && ChildDocument.FTER40.HasValue &&
                             ChildDocument.FTER40 != ParentDocument.SMSFAR1;
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.FTER.408029",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Income year for variation must match the year of return on the main form",
                    LongDescription = "Income year specified for the purpose of the FTE variation must match the year of return on the main form",
                    Location = "/tns:FTER/tns:RP/tns:ElectionOrVariationIncomeYear/tns:ElectionsFamilyTrustElectionStatusY",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408029" },
                        new ProcessMessageParameter { Name = "FTER40", Value = ChildDocument.FTER40.ToString() }
                    }
                });
            }
        }
        #endregion

        #region VR.ATO.FTER.408033
        //IF[FTER95] = "R" AND[FTER96] <> NULL AND[FTER96] <> PARENT RETURN:RP:pyin.xx.xx:Report.TargetFinancial.Year
        //    RETURN VALIDATION MESSAGE
        //ENDIF
        //[FTER95] = FTER:RP:Elections.FamilyTrustElectionRevocation.Code
        //[FTER96] = FTER:RP:Elections.FamilyTrustRevocationStatusEffective.Year
        private void VRATOFTER408033(List<ProcessMessageDocument> response)
        {
            bool assertion = !string.IsNullOrWhiteSpace(ChildDocument.FTER95) &&
                             ChildDocument.FTER95.ToUpper().Equals("R") && ChildDocument.FTER96.HasValue &&
                             ChildDocument.FTER96 != ParentDocument.SMSFAR1;
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.FTER.408390",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Income year of revocation must be the same as the year of return on the main form",
                    Location = "/tns:FTER/tns:RP/tns:FamilyTrustRevocation/tns:ElectionsStatusEffectiveY",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408033" },
                        new ProcessMessageParameter { Name = "FTER96", Value = ChildDocument.FTER96.ToString() }
                    }
                });
            }
        }
        #endregion

        #region VR.ATO.FTER.408112
        //WHERE PARENT RETURN EXISTS
        //IF[FTER95] = "E" AND[FTER40] <>  PARENT RETURN:RP:Elections.FamilyTrustElectionStatus.Year
        //    RETURN VALIDATION MESSAGE
        //ENDIF
        //[FTER95] = FTER:RP:Elections.FamilyTrustElectionRevocation.Code
        //[FTER40] = FTER:RP:Elections.FamilyTrustElectionStatus.Year
        private void VRATOFTER408112(List<ProcessMessageDocument> response)
        {
            bool assertion = !string.IsNullOrWhiteSpace(ChildDocument.FTER95) &&
                              ChildDocument.FTER95.ToUpper().Equals("E") && ChildDocument.FTER40.HasValue &&
                              !ChildDocument.FTER40.GetValueOrDefault().Equals(ParentDocument.SMSFAR162.GetValueOrDefault());
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.FTER.408377",
                    Severity = ProcessMessageSeverity.Error,
                    Description = @"Income year specified on main return form must equal the income year specified on the schedule",
                    Location = "/tns:FTER/tns:RP/tns:ElectionOrVariationIncomeYear/tns:ElectionsFamilyTrustElectionStatusY",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408112" },
                        new ProcessMessageParameter { Name = "FTER40", Value = ChildDocument.FTER40.ToString() }
                    }
                });
            }
        }
        #endregion
        
        #region VR.ATO.FTER.408162
        //WHERE PARENT RETURN EXISTS
        //IF[FTER57] > ((PARENT RETURN:RP:pyin.xx.xx:Report.TargetFinancial.Year)&"-06-30")
        //RETURN VALIDATION MESSAGE
        //    ENDIF
        //[FTER57] = FTER:RP:Elections.Revocation.Date
        private void VRATOFTER408162(List<ProcessMessageDocument> response)
        {
            bool assertion = ChildDocument.FTER57.HasValue && DateTime.Compare(ChildDocument.FTER57.Value,
                                 Convert.ToDateTime(string.Concat(ParentDocument.SMSFAR1.ToString(), "-06-30"))) > 0;
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.FTER.408389",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Revocation date must not be after 30 June of the year of return on the main form",
                    Location = "/tns:FTER/tns:RP/tns:FamilyTrustRevocation/tns:ElectionsD",
                    Parameters = new ProcessMessageParameters
                    {
                        new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408162" },
                        new ProcessMessageParameter { Name = "FTER57", Value = ChildDocument.FTER57.Value.ToString("yyyy-MM-dd") }
                    }
                });
            }
        }
        #endregion

        #region VR.ATO.FTER.408371

        // WHERE PARENT RETURN EXISTS
        // ^FTER173 <> ^ParentPeriodStartDate

        private void VRATOFTER408371(List<ProcessMessageDocument> response)
        {
            bool assertion = ParentDocument.RPStartDate.Value != ChildDocument.FTER173.Value;
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.FTER.408371",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Reporting period start date must match the period start date on the main form",
                    Location = "/tns:FTER/tns:RP/tns:PeriodStartD",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408371" } }
                });
            }
        }

        #endregion

        #region VR.ATO.FTER.408372

        // WHERE PARENT RETURN EXISTS
        // ^FTER174 <> ^ParentPeriodStartDate

        private void VRATOFTER408372(List<ProcessMessageDocument> response)
        {
            bool assertion = ParentDocument.RPEndDate.Value != ChildDocument.FTER174.Value;
            if (assertion)
            {
                response.Add(new ProcessMessageDocument
                {
                    Code = "CMN.ATO.FTER.408372",
                    Severity = ProcessMessageSeverity.Error,
                    Description = "Reporting period end date must match the period end date on the main form",
                    Location = "/tns:FTER/tns:RP/tns:PeriodEndD",
                    Parameters = new ProcessMessageParameters { new ProcessMessageParameter { Name = "RuleIdentifier", Value = "VR.ATO.FTER.408372" } }
                });
            }
        }

        #endregion
    }
}