module Legacy
  class UpdateJob < ::ApplicationJob
    def user_attributes
      @title = @user.title
      attr = @user.attributes.slice(*user_columns)
      attr['title_attributes'] = title_attributes
      attr['title_id'] = attr['title_attributes']['id'] # sync title_id in case of it's new record
      @billing_information = @user.billing_information
      attr['billing_information_attributes'] = billing_information_attributes if @billing_information
      attr
    end

    def user_columns
      ::User.column_names - %w[id title_id created_at updated_at]
    end

    def title_attributes
      @legacy_title ||= Legacy::Title.find_or_create_by(name: Legacy::Title.name_with_prefix(@title.name))
      attr = @title.attributes.slice(*title_columns)
      attr['id'] = @legacy_title.id
      attr['name'] = Legacy::Title.name_with_prefix(@title.name)
      attr['server_id'] = Legacy::Server.find_by(name: @title.server.name)&.id
      @title_provider_group_name = @title.title_provider_group_name
      if @title_provider_group_name
        attr['title_provider_group_name_attributes'] = title_provider_group_name_attributes
        attr['title_provider_group_name_id'] = attr['title_provider_group_name_attributes']['id']
      end
      attr
    end

    def title_columns
      ::Title.column_names - %w[id server_id visible country_id title_provider_group_name_id billing_company_id created_at updated_at]
    end

    def billing_information_attributes
      attr = @billing_information.attributes.slice(*billing_information_columns)
      attr['id'] = Legacy::BillingInformation.find_by(user_id: @legacy_user.id)&.id
      attr
    end

    def billing_information_columns
      ::BillingInformation.column_names - %w[id user_id created_at updated_at]
    end

    def title_provider_group_name_attributes
      @legacy_title_provider_group_name ||= Legacy::TitleProviderGroupName.find_or_create_by(name: Legacy::TitleProviderGroupName.name_with_prefix(@title_provider_group_name.name))
      attr = @title_provider_group_name.attributes.slice(*title_provider_group_name_columns)
      attr['id'] = @legacy_title_provider_group_name.id
      attr['name'] = Legacy::TitleProviderGroupName.name_with_prefix(@title_provider_group_name.name)
      attr['title_provider_groups_attributes'] = title_provider_groups_attributes
      attr
    end

    def title_provider_group_name_columns
      ::TitleProviderGroupName.column_names - %w[id name created_at updated_at]
    end

    def title_provider_groups_attributes
      title_provider_groups = @title_provider_group_name.title_provider_groups
      legacy_title_provider_groups = @legacy_title_provider_group_name.title_provider_groups

      provider_id = title_provider_groups.reduce({}) do |reducer, title_provider_group|
        reducer.tap do |r|
          provider = Legacy::Provider.create_with(name: title_provider_group.provider.name).find_or_create_by(string_key: title_provider_group.provider.string_key)
          r[provider.id] = title_provider_group.provider_id
        end
      end
      legacy_provider_id = legacy_title_provider_groups.map(&:provider_id)

      delete_attr = legacy_title_provider_groups.select { |a| a.provider_id.in?(legacy_provider_id - provider_id.keys) }.map do |legacy_title_provider_group|
        attr = {}
        attr['id'] = legacy_title_provider_group.id
        attr['_destroy'] = true
        attr
      end
      update_attr = title_provider_groups.select { |a| a.provider_id.in?(provider_id.slice(*provider_id.keys & legacy_provider_id).values) }.map do |title_provider_group|
        legacy_title_provider_group = legacy_title_provider_groups.detect { |legacy_title_provider_group| legacy_title_provider_group.provider_id == provider_id.invert[title_provider_group.provider_id] }
        attr = title_provider_group.attributes.slice(*title_provider_group_columns)
        attr['id'] = legacy_title_provider_group.id
        attr['authorizations_attributes'] = authorizations_attributes_for(title_provider_group.authorizations, legacy_title_provider_group.authorizations)
        attr.reject { |_, v| v.blank? }
      end.reject { |a| a['authorizations_attributes'].nil? }
      create_attr = title_provider_groups.select { |a| a.provider_id.in?(provider_id.slice(*provider_id.keys - legacy_provider_id).values) }.map do |title_provider_group|
        attr = title_provider_group.attributes.slice(*title_provider_group_columns)
        attr['provider_id'] = provider_id.invert[title_provider_group.provider_id]
        attr['authorizations_attributes'] = authorizations_attributes_for(title_provider_group.authorizations)
        attr.reject { |_, v| v.blank? }
      end
      delete_attr + update_attr + create_attr

    end

    def title_provider_group_columns
      ::TitleProviderGroup.column_names - %w[id titile_provider_group_name_id provider_id created_at updated_at]
    end

    def authorizations_attributes_for(authorizations, legacy_authorizations = [])
      permission_label_id = authorizations.map(&:permission_label_id)
      legacy_permission_label_id = legacy_authorizations.map(&:permission_label_id)
      delete_attr = legacy_authorizations.select { |a| a.permission_label_id.in?(legacy_permission_label_id - permission_label_id) }.map do |legacy_authorization|
        attr = {}
        attr['id'] = legacy_authorization.id
        attr['_destroy'] = true
        attr
      end
      create_attr = authorizations.select { |a| a.permission_label_id.in?(permission_label_id - legacy_permission_label_id) }.map do |authorization|
        attr = authorization.attributes.slice(*authorization_columns)
        attr
      end
      delete_attr + create_attr
    end

    def authorization_columns
      ::Authorization.column_names - %w[id title_provider_group_id created_at updated_at]
    end
  end
end
