class Admission::Applicants::ApplicationService < ApplicationService
  def initialize(id, options: [], missing: false)
    @id = id
    @options = options.map(&:to_sym)
    @missing_info = missing
  end

  def call
    return complete_props if @missing_info

    {}.tap do |props|
      props[:application] = application
      props[:admission_config] = admission_config
      props[:applicant_name] = applicant.full_name
      props[:welcome_message] = application.welcome_message
      props[:require_medical] = medical.available?
      props[:additional_fields_available] = additional_field.available?
      props[:additional_fields_present] = additional_field.fields_present?
      props[:agreements_present] = agreement.available?
      props[:essays_present] = essay.available?
      props[:attachments_present] = attachment.available?
      props[:documents_present] = document.available?
      props[:family_general_present] = family_profile_field.available?
      props[:family_additional_fields_available] = family_additional_field.available?
      props[:family_additional_fields_present] = family_additional_field.fields_present?
      props[:family_medical_present] = family_medical.available?
      props[:enrollment_config] = enrollment_class.config_props

      if @options.include?(:family_payment)
        props[:applicant_payment] = applicant
        props[:family_payment] = family_payment
        props[:payment_service] = if school.stripe_connect_account
          props[:stripe_processing_fees] = processing_fee_props
          {
            service: :stripe,
            credit_card: true,
            stripe_account_id: school.stripe_connect_account&.stripe_account_id,
            parents_pay_cc_fee: school.parents_pay_cc_fee
          }
        elsif school.school_config.tep_integration?
          { service: :tep, credit_card: true }
        elsif paya_config.enabled?
          {
            service: :paya,
            credit_card: paya_payment_methods.include?('cc'),
            ach: paya_payment_methods.include?('ach')
          }
        elsif payjunction_config.enabled?
          {
            service: :payjunction,
            publishable_key: payjunction_config.publishable_key,
            credit_card: payjunction_config.credit_card?,
            ach: payjunction_config.ach?
          }
        else
          {}
        end
      end

      if @options.include?(:profile_fields)
        props[:profile_fields] = profile_field.props
        props[:profile_fields_complete] = profile_field.completed?
      end

      if @options.include?(:medical)
        props[:medical] = medical.props
        props[:medical_complete] = medical.completed?
      end

      if @options.include?(:family_general)
        props[:family_profile_fields] = family_profile_field.props
        props[:family_revision] = family_profile_field.revision
        props[:family_revision_incomplete_fields] = family_profile_field.revision.incomplete_fields
      end

      if @options.include?(:additional_fields)
        props[:additional_fields] = additional_field.props
        props[:additional_fields_complete] = applicant.additional_fields_complete?
      end

      if @options.include?(:agreements)
        props[:agreements] = agreement.props
        props[:agreements_complete] = applicant.agreements_complete?
      end

      if @options.include?(:essays)
        props[:essays] = essay.props
        props[:essays_complete] = applicant.essays_complete?
      end

      props[:attachments] = attachment.props if @options.include?(:attachments)

      if @options.include?(:documents)
        props[:documents] = document.props
        props[:documents_complete] = applicant.documents_complete?
      end

      if @options.include?(:student_classes)
        props[:enrollment_classes] = enrollment_class.props
        props[:student_class_ids] = enrollment_class.student_class_ids
        props[:student_classes_complete] = enrollment_class.complete?
      end

      if @options.include?(:family_medical)
        props[:family_medical] = family_medical.props
        props[:family_medical_incomplete_fields] = family_medical.incomplete_fields
      end

      if @options.include?(:family_additional_fields)
        props[:family_additional_fields] = family_additional_field.props
        props[:family_additional_fields_complete] = family_additional_field.completed?
      end

      if @options.include?(:family_contacts)
        props[:family_contacts] = family_contact.props
        props[:non_primary_emergency_contact] = family_contact.non_primary_emergency_contact?
      end
    end
  end

  private
    def school
      @school ||= applicant.school
    end

    def applicant
      @applicant ||= Admission::Applicant.find_by(id: @id).decorate
    end

    def application
      @application ||= applicant.application
    end

    def profile_field
      @profile_field ||= Admission::Applicants::ProfileFieldService.new(applicant, application)
    end

    def medical
      @medical ||= Admission::Applicants::MedicalService.new(applicant, application)
    end

    def additional_field
      @additional_field ||=
        Admission::Applicants::AdditionalFieldService.new(applicant, application)
    end

    def agreement
      @agreement ||= Admission::Applicants::AgreementService.new(applicant, application)
    end

    def essay
      @essay ||= Admission::Applicants::EssayService.new(applicant, application)
    end

    def attachment
      @attachment ||= Admission::Applicants::AttachmentService.new(application)
    end

    def document
      @document ||= Admission::Applicants::DocumentService.new(applicant, application)
    end

    def enrollment_class
      @enrollment_class ||= Admission::Applicants::EnrollmentClassService.new(applicant)
    end

    def family_profile_field
      @family_profile_field ||=
        Admission::Applicants::FamilyGeneralService.new(applicant, application)
    end

    def family_additional_field
      @family_additional_field ||=
        Admission::Applicants::FamilyAdditionalFieldService.new(applicant, application)
    end

    def family_medical
      @family_medical ||= Admission::Applicants::FamilyMedicalService.new(applicant, application)
    end

    def family_contact
      @family_contact ||= Admission::Applicants::FamilyContactService.new(applicant, application)
    end

    def family_payment
      @family_payment ||= applicant.family.admission_families
        .find_or_initialize_by(school_year_id: admission_config.school_year_id)
    end

    def admission_config
      @admission_config ||= application.school.find_or_build_admission_config
    end

    def paya_config
      school.find_or_build_paya_config
    end

    def payjunction_config
      @payjunction_config ||= school.find_or_build_payjunction_config
    end

    def enrollment_config
      school.find_or_build_enrollment_config
    end

    def paya_payment_methods
      @paya_payment_methods ||= Paya::ProductService
        .call(school)['locationinfo']['product_transactions']
        .pluck('payment_method')
    end

    def processing_fee_props
      props = {}
      family_payment_amount = 0
      applicant_payment_amount = 0
      total_amount = 0

      if admission_config.family_payment
        family_payment_amount = (admission_config.payment_amount.to_f * 100).to_i
      end

      if application.payment
        applicant_payment_amount = (applicant.payment_amount.to_f * 100).to_i
      end

      if family_payment_amount > 0
        family_processing = Stripe::ProcessingService.new(school, family_payment_amount)
        props[:family] = family_processing.total_processing_fee_amount(false)
      end

      if applicant_payment_amount > 0
        applicant_processing = Stripe::ProcessingService.new(school, applicant_payment_amount)
        props[:applicant] = applicant_processing.total_processing_fee_amount(false)
      end

      total_amount += family_payment_amount unless family_payment.paid_at
      total_amount += applicant_payment_amount unless applicant.paid_at

      total_processing_fee = Stripe::ProcessingService.new(school, total_amount)
      props[:combined] = total_processing_fee.total_processing_fee_amount(false)
      props
    end

    def complete_props
      {
        applicant_id: applicant.id,
        application_id: application.id,
        profile_fields: profile_field.props,
        profile_fields_complete: profile_field.completed?,
        medical: medical.props,
        medical_complete: medical.completed?,
        additional_fields: additional_field.props,
        additional_fields_complete: applicant.additional_fields_complete?,
        agreements: agreement.props,
        agreements_complete: applicant.agreements_complete?,
        essays: essay.props,
        essays_complete: applicant.essays_complete?,
        documents: document.props,
        documents_complete: applicant.documents_complete?,
        non_primary_emergency_contact: family_contact.non_primary_emergency_contact?,
        family_revision_incomplete_fields: family_profile_field.revision.incomplete_fields,
        family_additional_fields: family_additional_field.props,
        family_additional_fields_complete: family_additional_field.completed?,
        family_medical: family_medical.props,
        family_medical_incomplete_fields: family_medical.incomplete_fields,
        student_classes_complete: enrollment_class.complete?
      }
    end
end
