class Admin::NodesController < Admin::AdminController
  before_action :set_node, only: %i[ edit update destroy children sort toggle ]

  helper_method :current_node_id, :open_node_ids

  # GET /nodes
  def index
    # Can be nil
    @node = Node.find_by(id: current_node_id) || Node.roots.first
  end


  # GET /nodes/1/edit
  def edit
    respond_to do |format|
      format.turbo_stream
      format.html
    end
  end

  # GET /nodes/tree /nodes/1/tree
  def tree
    @node = params[:id] ? Node.find(params[:id]) : Node.roots.first

    session[:current_node_id] = @node&.id

    respond_to do |format|
      format.turbo_stream
    end
  end


  # POST /nodes or /nodes.json
  def create
    @node = Node.new(node_params)
    @node.status = :status_published

    base_title = t("ui.untitled")
    title = base_title
    count = 0

    while @node.siblings.exists?(title: { I18n.locale => title })
      count += 1
      title = "#{base_title} #{count}"
    end

    @node.title = title

    respond_to do |format|
      if @node.save
        ensure_open_node_ids
        session[:open_node_ids] << @node.id unless session[:open_node_ids].include?(@node.id)

        format.turbo_stream
        format.html { redirect_to edit_admin_node_url(@node), notice: t("ui.category_created", category: t(@node.template, scope: "nodes.templates")) }
      else
        format.html { render :new, status: :unprocessable_entity }
      end
    end
  end


  # GET /nodes/1/children
  def children
    store_node_toggle_status

    respond_to do |format|
      format.turbo_stream
    end
  end


  # PATCH/PUT /nodes/1
  def update
    params[:node][:expires_at] ||= nil

    respond_to do |format|
      if @node.update(node_params)
        format.turbo_stream {
          flash.now[:notice] = t("ui.category_updated", category: t(@node.template, scope: "nodes.templates"))
        }
        format.html { redirect_to edit_node_url(@node), notice: t("ui.category_updated", category: t(@node.category, scope: "nodes.categories")) }
      else
        format.html { render :edit, status: :unprocessable_entity }
      end
    end
  end


  # DELETE /nodes/1
  def destroy
    if @node.destroy!
      @destroyed_node = @node
      @node = @node.parent
    end
    respond_to do |format|
      format.turbo_stream {
        flash.now[:notice] = t("ui.category_destroyed", category: t(@destroyed_node.category, scope: "nodes.categories"))
      }
      format.html { redirect_to nodes_url, notice: t(:"nodes.destroyed") }
    end
  end


  # PATCH /nodes/sort?id=
  # {"id"=>"2", "old_index"=>1, "new_index"=>4, "node"=>{"id"=>"2"}}
  def sort
    @node.insert_at(params[:new_index].to_i + 1)
    respond_to do |format|
      format.turbo_stream
    end
  end



  # Expand or collapse node in drawer
  # PATCH /nodes/toggle?id=1&expanded=true/false
  def toggle
    store_node_toggle_status
    head :ok
  end


private


  # Use callbacks to share common setup or constraints between actions.
  def set_node
    @node = Node.find(params[:id])
  end


  # Only allow a list of trusted parameters through.
  def node_params
    params.require(:node).permit(
      :parent_id,
      :title_en, :title_zh, :title_hr, :title_cs, :title_da, :title_nl, :title_fi, :title_fr, :title_fr_ca, :title_de, :title_hu, :title_it, :title_ja, :title_ko, :title_nb, :title_pl, :title_pt, :title_ro, :title_sr, :title_sk, :title_sl, :title_es, :title_sv, :title_uk,
      :page_title_en, :page_title_zh, :page_title_hr, :page_title_cs, :page_title_da, :page_title_nl, :page_title_fi, :page_title_fr, :page_title_fr_ca, :page_title_de, :page_title_hu, :page_title_it, :page_title_ja, :page_title_ko, :page_title_nb, :page_title_pl, :page_title_pt, :page_title_ro, :page_title_sr, :page_title_sk, :page_title_sl, :page_title_es, :page_title_sv, :page_title_uk,
      :page_description_en, :page_description_zh, :page_description_hr, :page_description_cs, :page_description_da, :page_description_nl, :page_description_fi, :page_description_fr, :page_description_fr_ca, :page_description_de, :page_description_hu, :page_description_it, :page_description_ja, :page_description_ko, :page_description_nb, :page_description_pl, :page_description_pt, :page_description_ro, :page_description_sr, :page_description_sk, :page_description_sl, :page_description_es, :page_description_sv, :page_description_uk,
      :slug_en, :slug_zh, :slug_hr, :slug_cs, :slug_da, :slug_nl, :slug_fi, :slug_fr, :slug_fr_ca, :slug_de, :slug_hu, :slug_it, :slug_ja, :slug_ko, :slug_nb, :slug_pl, :slug_pt, :slug_ro, :slug_sr, :slug_sk, :slug_sl, :slug_es, :slug_sv, :slug_uk,
      :template,
      :href_en, :href_zh, :href_hr, :href_cs, :href_da, :href_nl, :href_fi, :href_fr, :href_fr_ca, :href_de, :href_hu, :href_it, :href_ja, :href_ko, :href_nb, :href_pl, :href_pt, :href_ro, :href_sr, :href_sk, :href_sl, :href_es, :href_sv, :href_uk,
      :status,
      :page_description,
      :parent_id,
      :position,
      :published_at,
      :expires_at,
      :is_allowlist,
      excluded_locales: [],
      settings: [],
      tags_en: [], tags_zh: [], tags_hr: [], tags_cs: [], tags_da: [], tags_nl: [], tags_fi: [], tags_fr: [], tags_fr_ca: [], tags_de: [], tags_hu: [], tags_it: [], tags_ja: [], tags_ko: [], tags_nb: [], tags_pl: [], tags_pt: [], tags_ro: [], tags_sr: [], tags_sk: [], tags_sl: [], tags_es: [], tags_sv: [], tags_uk: [],
      attachments_attributes: [
        :id, :asset_id,
        :body_en, :body_zh, :body_hr, :body_cs, :body_da, :body_nl, :body_fi, :body_fr, :body_fr_ca, :body_de, :body_hu, :body_it, :body_ja, :body_ko, :body_nb, :body_pl, :body_pt, :body_ro, :body_sr, :body_sk, :body_sl, :body_es, :body_sv, :body_uk,
        :fg_color, :bg_color, :alignment, :template, :position, :_destroy
      ]
    )
  end


  def current_node_id
    session[:current_node_id]
  end


  def open_node_ids
    Array(session[:open_node_ids])
  end


  def ensure_open_node_ids
    session[:open_node_ids] ||= []
  end


  def store_node_toggle_status
    ensure_open_node_ids

    if params[:expanded] == false
      session[:open_node_ids].delete(@node.id)
    else
      session[:open_node_ids] << @node.id unless session[:open_node_ids].include?(@node.id)
    end
  end
end
