class UsuariosController < ApplicationController
	include ControllerConcern

	before_action :authenticate_usuario!, except: [:edit_password_via_email, :solicitacao_novo_usuario, :create_usuario, :imprimir, :atualiza_senha_resetada]
	before_action :autoriza_usuario!, except: [:show, :edit_password_via_email, :edit_password_usuario, :update_password_usuario, :solicitacao_novo_usuario, :create_usuario, :imprimir, :termo_siafic, :aceitar_termo_siafic, :atualiza_senha_resetada]
	before_action :set_usuario, only: [:edit, :edit_password, :update, :update_password, :destroy, :editar_unidades_orcamentarias, :show, :gerar_token, :aprovar, :termo_siafic, :aceitar_termo_siafic]
	before_action :get_perfis, only: [:edit, :update, :new, :create]
	before_action :impede_de_criar_admin_se_nao_tiver_permissao, only: [:create, :update]
	before_action :disponibiliza_dependencias, onyl: [:new, :edit]

	# GET /usuarios
	# GET /usuarios.json
	def index
		if current_usuario.desenvolvedor?
			@q = Usuario.order(:id).ransack(query_params)
		else
			@q = Usuario.where('desenvolvedor IS NOT TRUE').order(:id).ransack(query_params)
		end

		@usuarios = @q.result.paginate(:page => params[:page], :per_page => 30)
	end

	# GET /usuarios/new
	def new
		@usuario = Usuario.new
	end

	def show
	end

	def edit_password_via_email
		usuario = Usuario.find_by_email(params[:email])
		if usuario.try(:email).present?
			usuario.send_reset_password_instructions
			redirect_to new_usuario_session_path
			flash[:success] = "Email enviado com sucesso!"
		else
			redirect_to new_usuario_session_path
			flash[:alert] = 'Email não existe'
		end
	end

	# GET /usuarios/1/edit
	def edit

	end

	def edit_password_usuario
		@usuario = Usuario.find(current_usuario.id)
	end

	def update_password_usuario
		@usuario = Usuario.find(current_usuario.id)
		if @usuario.update(usuario_params)
			redirect_to root_path, notice: 'Senha alterada com sucesso.'
		else
			render :edit_password_usuario
		end
	end

	def edit_password
	end

	# POST /usuarios/atualiza_senha_resetada
	def atualiza_senha_resetada
		nova_senha_params = atualiza_senha_resetada_params
		decrypted_token = Devise.token_generator.digest(self, :reset_password_token, nova_senha_params[:reset_password_token])
		@usuario = Usuario.find_by(reset_password_token: decrypted_token)

		begin
			if @usuario.update(nova_senha_params)
				redirect_to new_usuario_session_path, success: 'Senha alterada com sucesso.'
			else
				render "devise/passwords/edit"
			end
		rescue => e
			redirect_to new_usuario_session_path, alert: 'Token inválido.'
		end
	end

	def update_password
		if @usuario.update(password_params)
			redirect_to usuarios_path, notice: 'Senha alterada com sucesso.'
		else
			render :edit_password
		end
	end

	# POST /usuarios
	# POST /usuarios.json
	def create
		@usuario = Usuario.new(usuario_params)
		if @usuario.save
			redirect_to usuarios_path, notice: 'Usuário cadastrado com sucesso.'
		else
			render :new
		end
	end

	# PATCH/PUT /usuarios/1
	# PATCH/PUT /usuarios/1.json
	def update
		disponibiliza_dependencias
		@tela = params[:tela_atual] if params[:tela_atual].present?
		if @usuario.update(usuario_params)
			redirect_to @usuario, notice: 'Usuário atualizado com sucesso.'
		else
			if !contexto_atual.present? && @tela.blank?
				render :edit
			else
				render :editar_unidades_orcamentarias
			end
		end
	end

	def editar_unidades_orcamentarias
		disponibiliza_dependencias
		if @usuario.unidades_orcamentarias_por_usuario.empty?
			@usuario.unidades_orcamentarias_por_usuario.build
		end
	end

	# DELETE /usuarios/1
	# DELETE /usuarios/1.json
	def destroy
		mensagem = apaga_e_retorna_mensagem(@usuario)
		redirect_to usuarios_url, mensagem
	end

  #----------------------------------------------------------------------------#

  def solicitacao_novo_usuario
    disponibiliza_dependencias_para_novo_usuario
		@usuario = Usuario.new
	end

  def create_usuario
    disponibiliza_dependencias_para_novo_usuario
    @usuario = Usuario.new(usuario_params)
		if @usuario.save
			if @usuario.unidades_orcamentarias_por_usuario.empty?
				usuario_params[:unidades_orcamentarias_por_usuario_attributes].each do |unid|
					unid[1..unid.size - 1].flatten.each do |unidade|
						@usuario.unidades_orcamentarias_por_usuario.build(unidade_orcamentaria_id: unidade[:unidade_orcamentaria_id], criado_por_pagina: true)
					end
				end
				@usuario.save!
			end
			redirect_to new_usuario_session_path
      flash[:success] = 'Usuário cadastrado com sucesso. Aguarde seu cadastro ser aprovado por um administrador.'
    else
			render :solicitacao_novo_usuario
      flash[:success] = 'Ocorreu um erro, por favor confira os dados.'
		end
  end

	def termo_siafic
		redirect_to seleciona_modulo_path, alert: 'Somente o próprio usuário pode assinar o termo.' if @usuario.id != current_usuario.id
	end

	def aceitar_termo_siafic
		if usuario_params[:concordo] == "1"
			@usuario.data_do_termo = Date.today
			@usuario.save(validate: false)
			redirect_to @usuario, success: 'A data de assinatura do termo foi salva, a impressão do termo está disponível.'
		else
			redirect_to termo_siafic_usuario_path, alert: 'Não foi possível salvar as informações, você deve aceitar o termo.'
		end
	end

  def imprimir
    relatorio = params[:relatorio]
    @usuario = Usuario.find(params[:usuario_id]) if params[:usuario_id].present?
    
    if respond_to? relatorio.to_s, :private
      loa = CombinePDF.new
      loa << CombinePDF.parse(send(relatorio))
      loa.number_pages(location: :bottom_right, margin_from_height: 0, number_format: '%s', font_size: 8)
      send_data loa.to_pdf, filename: "#{relatorio}.pdf", type: "application/pdf", disposition: 'inline'
    else
      redirect_to :back, alert: 'Termo não encontrado'
    end
  end

  def termo_de_responsabilidade
    @configuracoes = Configuracao.last

    render_to_string pdf: "Termo de Responsabilidade",
      template: "usuarios/termo_de_responsabilidade.pdf.slim",
      orientation: 'Portrait',
      disable_smart_shrinking: true,

      dpi: '96',
      header: {
        html: {
          template: 'layouts/_cabecalho_pdf.html.slim',
          locals: {
            titulo1: "TERMO DE RESPONSABILIDADE DE USO DO SISTEMA GERENCIAL",
            titulo2: ""
          }
        },
        spacing: 0
      },
      footer: {
        html: {
          template: 'layouts/_rodape_pdf.html.slim'
        }
      },
      margin: @configuracoes.margens_customizadas
  end

  #----------------------------------------------------------------------------#

	def nao_aprovados
		return if bloqueia_usuario_com_base_em 'aprovar'
		@q = Usuario.nao_aprovados.order(:id).ransack(query_params)
		@usuarios = @q.result.paginate(:page => params[:page], :per_page => 30)
	end

	def aprovar
		if @usuario.nao_aprovado?
			if @usuario.update_attributes(aprovado: true, aprovado_por: current_usuario)
				redirect_to nao_aprovados_usuarios_path, success: "Usuário #{@usuario.nome_completo.try(:upcase)} liberado para acesso ao sistema."
			else
				redirect_to nao_aprovados_usuarios_path, alert: "Um erro ocorreu ao tentar liberar o acesso ao sistema para #{@usuario.nome_completo.try(:upcase)}."
			end
		else
			redirect_to nao_aprovados_usuarios_path, alert: "Usuário já aprovado anteriormente."
		end
	end

	def gerar_token
		if @usuario.present?
			if current_usuario.id == @usuario.id
				@usuario.gerar_credenciais
				redirect_to usuario_path(@usuario) + "?tab=acesso_api", notice: "Credenciais geradas com sucesso."
			else
				redirect_to usuario_path(@usuario) + "?tab=acesso_api", alert: "Não foi possível gerar as credenciais do usuário."
			end
		else
			redirect_to usuarios_path, alert: "Usuário não encontrado."
		end
	end

	def valida_senha
		usuario = Usuario.find(current_usuario.id)

		respond_to do |format|
			format.json { render :html => usuario.valid_password?(params[:senha]) }
			format.html
		end
	end

	def disponibiliza_dependencias
		@permissao_unidades_orcamentarias = Usuario.nivel_de_permissao_a_unidades
		@unidades_orcamentarias = Loa::UnidadeOrcamentaria.all
		@tipo_de_poder = Usuario.tipos_de_poder
	end

  def disponibiliza_dependencias_para_novo_usuario
    @unidades_orcamentarias = Loa::UnidadeOrcamentaria.joins(:orgao).where("loa_orgaos.orcamento_id = ?", Orcamento.last.id)
		@permissao_unidades_orcamentarias = Usuario.nivel_de_permissao_a_unidades
    @tipo_de_poder = Usuario.tipos_de_poder
    @perfis = [
      ['Administrador', 1],
      ['Secretário', 2],
      ['Setor de Compras', 3],
      ['Comissão de Licitação', 4],
      ['Procuradoria', 5],
      ['Contabilidade', 6],
      ['Controladoria', 7],
      ['Setor Administrativo', 8],
      ['Setor Administrativo IPM', 9],
      ['Setor de Obras', 10]
    ]
  end

	private
	# Use callbacks to share common setup or constraints between actions.
	def set_usuario
		@usuario = Usuario.find(params[:id])
	end

	def get_perfis
		if current_usuario.administrador?
			@perfis = Perfil.order(:nome)
		else
			@perfis = @perfis.where.not( id: Perfil.administrador.id )
		end
	end

	def impede_de_criar_admin_se_nao_tiver_permissao
		params[:usuario][:perfil_id] = nil unless current_usuario.administrador?
	end

	# Never trust parameters from the scary internet, only allow the white list through.
	def usuario_params
		params.require(:usuario).permit(:nivel_de_permissao_a_unidades,
			:email, :email_institucional, :nome_de_usuario, :nome_completo, :receber_email, :numero_da_matricula, :cargo, :tipo_de_poder,
			:password, :password_confirmation, :perfil_id, :siafic, :cpf, :concordo, unidades_orcamentarias_por_usuario_attributes: [:id, :usuario_id, :unidade_orcamentaria_id, :_destroy]
		)
	end

	def password_params
		params.require(:usuario).permit(:password, :password_confirmation)
	end

	def atualiza_senha_resetada_params
		params.require(:usuario).permit(:password, :password_confirmation, :reset_password_token)
	end
end
