# frozen_string_literal: true

# Forma de ingreso a Sutty
class ApplicationController < ActionController::Base
  include ExceptionHandler
  include Pundit

  protect_from_forgery with: :null_session, prepend: true

  before_action :prepare_exception_notifier
  before_action :configure_permitted_parameters, if: :devise_controller?
  before_action :notify_unconfirmed_email, unless: :devise_controller?
  around_action :set_locale

  rescue_from Pundit::NilPolicyError, with: :page_not_found
  rescue_from ActionController::RoutingError, with: :page_not_found
  rescue_from ActionController::ParameterMissing, with: :page_not_found

  before_action do
    Rack::MiniProfiler.authorize_request if current_usuarie&.email&.ends_with?('@' + ENV.fetch('SUTTY', 'sutty.nl'))
  end

  # No tenemos índice de sutty, vamos directamente a ver el listado de
  # sitios
  def index
    redirect_to sites_path
  end

  private

  def notify_unconfirmed_email
    return unless current_usuarie
    return if current_usuarie.confirmed?

    I18n.with_locale(current_usuarie.lang) do
      flash[:notice] ||= I18n.t('devise.registrations.signed_up')
    end
  end

  def uuid?(string)
    /[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/ =~ string
  end

  # Encontrar un sitio por su nombre
  def find_site
    id = params[:site_id] || params[:id]

    unless (site = current_usuarie&.sites&.find_by_name(id))
      raise SiteNotFound
    end

    site
  end

  # Devuelve el idioma actual y si no lo encuentra obtiene uno por
  # defecto.
  #
  # Esto se refiere al idioma de la interfaz, no de los artículos.
  #
  # @return [String,Symbol]
  def current_locale
    session[:locale] = params[:change_locale_to] if params[:change_locale_to].present?

    session[:locale] || current_usuarie&.lang || I18n.locale
  end

  # El idioma es el preferido por le usuarie, pero no necesariamente se
  # corresponde con el idioma de los artículos, porque puede querer
  # traducirlos.
  def set_locale(&action)
    I18n.with_locale(current_locale, &action)
  end

  # Muestra una página 404
  def page_not_found
    render 'application/page_not_found', status: :not_found
  end

  # Necesario para poder acceder a Blazer.  Solo les usuaries de este
  # sitio pueden acceder al panel.
  def require_usuarie
    site = find_site
    authorize SiteBlazer.new(site)

    # Necesario para los breadcrumbs.
    ActionView::Base.include Loaf::ViewExtensions unless ActionView::Base.included_modules.include? Loaf::ViewExtensions

    breadcrumb current_usuarie.email, main_app.edit_usuarie_registration_path
    breadcrumb 'sites.index', main_app.sites_path, match: :exact
    breadcrumb site.title, main_app.site_path(site), match: :exact
    breadcrumb 'stats.index', root_path, match: :exact
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: Usuarie::CONSENT_FIELDS)
    devise_parameter_sanitizer.permit(:account_update, keys: %i[lang])
  end

  def prepare_exception_notifier
    request.env['exception_notifier.exception_data'] = { usuarie: current_usuarie }
  end

  # Olvidar el idioma elegido antes de iniciar la sesión y reenviar a
  # los sitios en el idioma de le usuarie.
  def after_sign_in_path_for(resource)
    session[:locale] = nil

    sites_path
  end
end