class UserController < ApplicationController
  include ApplicationHelper
  include RollenHelper
  include StationHelper

  helper_method :sort_column, :sort_direction

  def check_ability!
    return if [:home, :edit_password, :update_password, :save_filter, :show, :info].include? action_name.to_sym
    unless current_user.hat_berechtigung?(Rollen::Berechtigung::Verwaltung_Zugangsverwaltung_bearbeiten) || current_user.hat_berechtigung?(Rollen::Berechtigung::Verwaltung_Zugangsverwaltung_ansehen)
      raise CanCan::AccessDenied.new
    end
  end

  def home
    hinweis = anmeldungs_hinweis
    render locals: {
      hinweis: hinweis,
    }
  end

  def show
    rollen = Rollen::Rolle.all
    messstellen = StammdatenContext::GaugingStation.all
    betreiber = StammdatenContext::Operator.all
    eigentuemer = StammdatenSLContext::Eigentuemer.all
    messnetze = StammdatenSLContext::Messnetz.select(:messnetz_nr, :messnetz).order(:messnetz).as_json

    render locals: {
      messstellen: messstellen,
      betreiber: betreiber,
      eigentuemer: eigentuemer,
      messnetze: messnetze,
      rollen_hash: Hash[rollen.map { |it| [it.key, it] }],
    }
  end

  def index
    @users = User.order("#{params[:sort]} #{params[:direction]}").to_a
    if params[:sort] == 'role'
      @users.sort_by! { |user| user.role.name }
    end
    respond_to do |format|
      format.csv {
        csv = Export::FormatCSV.new
        filename = t('user_export_filename', date: ldate(Date.today)) + '.csv'
        send_data csv.write(@users, export_columns), filename: filename
      }
    end
  end

  def new
    @station = last_selected_station
    @user = User.new
    @user.active = true
    render locals: {selectable_stations: selectable_stations, selectable_operators: selectable_operators,
                    selectable_roles: selectable_roles, selectable_berechtigungen: selectable_berechtigungen}
  end

  def create
    @station = last_selected_station
    @user = User.new(permitted_params)
    @user.confirmed_at = Time.now
    @user.rollen = params[:rollen]
    @user.berechtigungen = params[:berechtigungen]
    @user.abilities = 'READ_ONLY'

    if @user.save
      flash.now[:notice] = t('notice.update')
    else
      flash.now[:alert] = t('alert.update')
      render action: 'new', locals: {selectable_stations: selectable_stations, selectable_operators: selectable_operators,
                                     selectable_roles: selectable_roles, selectable_berechtigungen: selectable_berechtigungen}
      return
    end
    refresh_users_mv

    BerechtigungsCache.instance.clear

    redirect_to verwaltung_zugangsverwaltung_path(@station.id)
  end

  def edit
    @station = last_selected_station
    @user = User.find(params[:id])
    @back_path = verwaltung_zugangsverwaltung_path(@station.id)
    render locals: {selectable_stations: selectable_stations, selectable_operators: selectable_operators,
                    selectable_roles: selectable_roles, selectable_berechtigungen: selectable_berechtigungen}
  end

  def update
    @station = last_selected_station
    @user = User.find(params[:id])
    @back_path = verwaltung_zugangsverwaltung_path(@station.id)

    @user.rollen = params[:rollen]
    @user.berechtigungen = params[:berechtigungen]

    pp = permitted_params.delete_if {|key, value| key == 'password' && value.blank?}
    if @user.update(pp)
      flash[:notice] = t('notice.update')
    else
      flash.now[:alert] = t('alert.update')
      render action: 'edit', locals: {selectable_stations: selectable_stations, selectable_operators: selectable_operators,
                                      selectable_roles: selectable_roles, selectable_berechtigungen: selectable_berechtigungen}
      return
    end
    refresh_users_mv

    BerechtigungsCache.instance.clear

    redirect_to verwaltung_zugangsverwaltung_path(@station.id)
  end

  def edit_password
    @user = current_user
  end

  def update_password
    @user = current_user
    if @user.update(params[:user].permit(:password, :password_confirmation))
      flash[:notice] = t('notice.update')
    else
      flash.now[:alert] = t('alert.update')
      render action: 'edit_password'
      return
    end
    redirect_to startpage_path
  end

  def info
    users = User.all.map do |user|
      {id: user.id, title: user.username}
    end
    render json: users
  end

private

  def anmeldungs_hinweis
    anwendungs_konfiguration = VerwaltungContext::KonfigurationAnwendung.first
    if anwendungs_konfiguration.nil?
      return {text: '', farbe: ''}
    end
    unless anwendungs_konfiguration.ist_anmeldungs_hinweistext_addressat?(current_user)
      return {text: '', farbe: ''}
    end
    return {
      text: anwendungs_konfiguration.hinweistext_anmeldung || '',
      farbe: anwendungs_konfiguration.hinweistext_anmeldung_farbe || 'info',
    }
  end

  def by_last_seen(a, b)
    if a.last_seen && b.last_seen
      b.last_seen <=> a.last_seen
    else
      a.last_seen ? -1 : 1
    end
  end

  def permitted_params
    params[:user].permit(:username, :password, :active, :email, :first_name, :last_name,
                         :organisationseinheiten, :bemerkung, :rollen, :berechtigungen)
  end

  def sort_column
    User.column_names.include?(params[:sort]) ? params[:sort] : 'last_name'
  end

  def sort_direction
    %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
  end

  def sort_nulls
    (sort_direction == 'asc') ? 'nulls first' : 'nulls last'
  end

  def export_columns
    [
      Export::Column.new('last_name', I18n.t('activerecord.attributes.user.last_name'), nil) { |user| user.last_name },
      Export::Column.new('first_name', I18n.t('activerecord.attributes.user.first_name'), nil) { |user| user.first_name },
      Export::Column.new('username', I18n.t('activerecord.attributes.user.username'), nil) { |user| user.username },
      Export::Column.new('email', I18n.t('activerecord.attributes.user.email'), nil) { |user| user.email },
      Export::Column.new('organisationseinheiten', I18n.t('activerecord.attributes.user.organisationseinheiten'), nil) { |user| user.organisationseinheiten_string },
      Export::Column.new('active', I18n.t('activerecord.attributes.user.active'), nil) { |user| yes_no(user.active?) }
    ]
  end

  def yes_no(value)
    value ? 'ja' : 'nein'
  end

  def refresh_users_mv
    if ENV['MARLIN_PEGELDATEN_DB_URL']&.start_with?('jdbc:oracle')
      ActiveRecord::Base.connection.execute("BEGIN refresh_mv_pegeldaten_users; END;")
    end
  end
end