<commit_before># frozen_string_literal: true

module GobiertoAdmin
  module GobiertoPlans
    class NodeForm < BaseForm
      include ::GobiertoAdmin::PermissionsGroupHelpers

      attr_accessor(
        :id,
        :plan_id,
        :name_translations,
        :starts_at,
        :ends_at,
        :options_json,
        :admin,
        :position,
        :force_new_version
      )
      attr_writer(
        :category_id,
        :status_id,
        :visibility_level,
        :moderation_visibility_level,
        :moderation_stage,
        :disable_attributes_edition,
        :progress,
        :published_version,
        :version,
        :external_id,
        :publish_last_version_automatically,
        :minor_change
      )

      validates :plan, :admin, presence: true
      validates :progress, presence: true, if: -> { @passed_attributes.include?("progress") }
      validates :category, :name_translations, presence: true, if: -> { allow_edit_attributes? }
      validates :status_id, presence: true, if: -> { allow_edit_attributes? && statuses_vocabulary.present? }
      validate :options_json_format
      validate :external_id_uniqueness_by_plan

      delegate :persisted?, to: :node
      delegate :site_id, :statuses_vocabulary, to: :plan

      def initialize(options = {})
        options = options.to_h.with_indifferent_access
        ordered_options = options.slice(:id, :plan_id, :admin).merge!(options)
        @passed_attributes = ordered_options.keys
        @publication_updated = false
        super(ordered_options)
        set_publication_version
      end

      def save
        check_visibility_level if allow_edit_attributes?
        save_node if valid?
      end

      def plan
        @plan ||= ::GobiertoPlans::Plan.find_by(id: plan_id)
      end

      def site
        Site.find_by(id: site_id)
      end

      def node
        @node ||= ::GobiertoPlans::Node.find_by(id: id).presence || build_node
      end
      alias record node
      alias project node

      def category
        @category ||= plan.categories.find_by(id: category_id)
      end

      def category_id
        @category_id ||= node.categories.where(vocabulary: plan.categories_vocabulary).first&.id
      end

      def category_options
        @category_options ||= begin
                                enabled_level = plan.categories_vocabulary.maximum_level
                                plan.categories_vocabulary.ordered_flatten_terms_tree.map do |term|
                                  [ActiveSupport::SafeBuffer.new("#{"&nbsp;" * 6 * term.level} #{term.name}".strip), term.level == enabled_level ? term.id : "disabled"]
                                end
                              end
      end

      def statuses_options
        @statuses_options ||= plan.statuses_vocabulary.terms.sorted.map { |term| [term.name, term.id] }
      end

      def progress_options
        @progress_options ||= begin
                                divisions = 4
                                (0..divisions).map do |div|
                                  progress_option(div.to_f / divisions * 100.0)
                                end +
                                  [["- - - -", "disabled"]] +
                                  (0..100).map { |percentage| progress_option(percentage) }
                              end
      end

      def progress_value
        @progress_value ||= progress.present? ? progress.to_i.to_s : nil
      end

      def options
        @options ||= begin
                       return nil if options_json.blank?

                       JSON.parse(options_json)
                     end
      end

      def visibility_level
        @visibility_level ||= moderation_visibility_level || node.visibility_level || "draft"
      end

      def progress
        @progress ||= node.progress || 0.0
      end

      def moderation_stage
        @moderation_stage ||= node.moderation_stage
      end

      def allow_edit_attributes?
        !disable_attributes_edition && (moderation_policy.edit? || allow_moderate?)
      end

      def allow_moderate?
        moderation_policy.moderate?
      end

      def moderation_visibility_level
        moderation_policy.moderate? ? @moderation_visibility_level : nil
      end

      def status_id
        return unless statuses_vocabulary && statuses_vocabulary.terms.where(id: @status_id).exists?

        @status_id
      end

      def attributes_updated?
        return if @node.new_record? || !allow_edit_attributes?

        nodes_attributes_differ?(set_node_attributes, versioned_node)
      end

      def publication_updated?
        @publication_updated
      end

      def version_index
        return unless @version && @version.to_i < node.versions.length

        @version.to_i - node.versions.length
      end

      def external_id
        @external_id ||= node.external_id || node.scoped_new_external_id(plan.nodes)
      end

      def publish_last_version_automatically
        @publish_last_version_automatically ||= plan.publish_last_version_automatically? && !minor_change
      end

      def minor_change
        return unless @minor_change.present?

        @minor_change == "1"
      end

      private

      def has_versions?<commit_msg>Fix bug trying to publish new projects<commit_after># frozen_string_literal: true

module GobiertoAdmin
  module GobiertoPlans
    class NodeForm < BaseForm
      include ::GobiertoAdmin::PermissionsGroupHelpers

      attr_accessor(
        :id,
        :plan_id,
        :name_translations,
        :starts_at,
        :ends_at,
        :options_json,
        :admin,
        :position,
        :force_new_version
      )
      attr_writer(
        :category_id,
        :status_id,
        :visibility_level,
        :moderation_visibility_level,
        :moderation_stage,
        :disable_attributes_edition,
        :progress,
        :published_version,
        :version,
        :external_id,
        :publish_last_version_automatically,
        :minor_change
      )

      validates :plan, :admin, presence: true
      validates :progress, presence: true, if: -> { @passed_attributes.include?("progress") }
      validates :category, :name_translations, presence: true, if: -> { allow_edit_attributes? }
      validates :status_id, presence: true, if: -> { allow_edit_attributes? && statuses_vocabulary.present? }
      validate :options_json_format
      validate :external_id_uniqueness_by_plan

      delegate :persisted?, to: :node
      delegate :site_id, :statuses_vocabulary, to: :plan

      def initialize(options = {})
        options = options.to_h.with_indifferent_access
        ordered_options = options.slice(:id, :plan_id, :admin).merge!(options)
        @passed_attributes = ordered_options.keys
        @publication_updated = false
        super(ordered_options)
        set_publication_version
      end

      def save
        check_visibility_level if allow_edit_attributes?
        save_node if valid?
      end

      def plan
        @plan ||= ::GobiertoPlans::Plan.find_by(id: plan_id)
      end

      def site
        Site.find_by(id: site_id)
      end

      def node
        @node ||= ::GobiertoPlans::Node.find_by(id: id).presence || build_node
      end
      alias record node
      alias project node

      def category
        @category ||= plan.categories.find_by(id: category_id)
      end

      def category_id
        @category_id ||= node.categories.where(vocabulary: plan.categories_vocabulary).first&.id
      end

      def category_options
        @category_options ||= begin
                                enabled_level = plan.categories_vocabulary.maximum_level
                                plan.categories_vocabulary.ordered_flatten_terms_tree.map do |term|
                                  [ActiveSupport::SafeBuffer.new("#{"&nbsp;" * 6 * term.level} #{term.name}".strip), term.level == enabled_level ? term.id : "disabled"]
                                end
                              end
      end

      def statuses_options
        @statuses_options ||= plan.statuses_vocabulary.terms.sorted.map { |term| [term.name, term.id] }
      end

      def progress_options
        @progress_options ||= begin
                                divisions = 4
                                (0..divisions).map do |div|
                                  progress_option(div.to_f / divisions * 100.0)
                                end +
                                  [["- - - -", "disabled"]] +
                                  (0..100).map { |percentage| progress_option(percentage) }
                              end
      end

      def progress_value
        @progress_value ||= progress.present? ? progress.to_i.to_s : nil
      end

      def options
        @options ||= begin
                       return nil if options_json.blank?

                       JSON.parse(options_json)
                     end
      end

      def visibility_level
        @visibility_level ||= moderation_visibility_level || node.visibility_level || "draft"
      end

      def progress
        @progress ||= node.progress || 0.0
      end

      def moderation_stage
        @moderation_stage ||= node.moderation_stage
      end

      def allow_edit_attributes?
        !disable_attributes_edition && (moderation_policy.edit? || allow_moderate?)
      end

      def allow_moderate?
        moderation_policy.moderate?
      end

      def moderation_visibility_level
        moderation_policy.moderate? ? @moderation_visibility_level : nil
      end

      def status_id
        return unless statuses_vocabulary && statuses_vocabulary.terms.where(id: @status_id).exists?

        @status_id
      end

      def attributes_updated?
        return unless allow_edit_attributes?
        return true if @node.new_record?

        nodes_attributes_differ?(set_node_attributes, versioned_node)
      end

      def publication_updated?
        @publication_updated
      end

      def version_index
        return unless @version && @version.to_i < node.versions.length

        @version.to_i - node.versions.length
      end

      def external_id
        @external_id ||= node.external_id || node.scoped_new_external_id(plan.nodes)
      end

      def publish_last_version_automatically
        @publish_last_version_automatically ||= plan.publish_last_version_automatically? && !minor_change
      end

      def minor_change
        return unless @minor_change.present?

        @minor_change == "1"
      end

      private

      def has_versions?
{'fraction_non_alphanumeric': 0.08139534883720931, 'fraction_numerical': 0.0026470032142181885, 'mean_word_length': 1.9542027366657357, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5623401', 'n_tokens_mistral': 3054, 'n_tokens_neox': 2881, 'n_words': 582}