module Panda
  module CMS
    class PagesController < ApplicationController
      include ActionView::Helpers::TagHelper

      before_action :check_login_required, only: [:root, :show]
      before_action :handle_redirects, only: [:root, :show]
      after_action :record_visit, only: [:root, :show], unless: :ignore_visit?

      def root
        params[:path] = ""
        show
      end

      def show
        page = if @overrides&.dig(:page_path_match)
          Panda::CMS::Page.find_by(path: @overrides.dig(:page_path_match))
        else
          Panda::CMS::Page.find_by(path: "/" + params[:path].to_s)
        end

        Panda::CMS::Current.page = page || Panda::CMS::Page.find_by(path: "/404")
        if @overrides
          Panda::CMS::Current.page.title = @overrides&.dig(:title) || page.title
        end

        layout = page&.template&.file_path

        if page.nil? || page.status == "archived" || layout.nil?
          # This works for now, but we may want to override in future (e.g. custom 404s)
          render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found and return
        end

        template_vars = {
          page: page,
          title: Panda::CMS::Current.page&.title || Panda::CMS.config.title
        }

        render inline: "", assigns: template_vars, status: :ok, layout: layout
      end

      private

      def handle_redirects
        current_path = "/" + params[:path].to_s
        redirect = Panda::CMS::Redirect.find_by(origin_path: current_path)

        if redirect
          redirect.increment!(:visits)

          # Check if the destination is also a redirect
          next_redirect = Panda::CMS::Redirect.find_by(origin_path: redirect.destination_path)
          if next_redirect
            next_redirect.increment!(:visits)
            redirect_to next_redirect.destination_path, status: redirect.status_code and return
          end

          redirect_to redirect.destination_path, status: redirect.status_code and return
        end
      end

      def check_login_required
        if Panda::CMS.config.require_login_to_view && !user_signed_in?
          redirect_to panda_cms_maintenance_path and return
        end
      end

      def ignore_visit?
        # Ignore visits from bots (TODO: make this configurable)
        return true if /bot/i.match?(request.user_agent)
        # Ignore visits from Honeybadger
        return true if request.headers.to_h.key? "Honeybadger-Token"

        false
      end

      def record_visit
        RecordVisitJob.perform_later(
          url: request.url,
          user_agent: request.user_agent,
          referrer: request.referrer,
          ip_address: request.remote_ip,
          page_id: Panda::CMS::Current.page&.id,
          current_user_id: current_user&.id,
          params: params.to_unsafe_h.except(:controller, :action, :path),
          visited_at: Time.zone.now
        )
      end

      def create_redirect_if_path_changed
        if path_changed? && path_was.present?
          Panda::CMS::Redirect.create!(
            origin_path: path_was,
            destination_path: path,
            status_code: 301
          )
        end
      end
    end
  end
end