<?php

require_once 'sistema/controllers/UsuarioController.php';
require_once '../library/Agro/RecaptchaEnterprise.php';

class LoginController extends Zend_Controller_Action {
    private $protocoloUrlNovaSenha = 'https://';
    private $parametrosUrlNovaSenha = '/login/novasenha/url/';
    private $urlNovaSenha = 'agronet.agrobrasilseguros.com.br';
    protected $ambienteProducao = false;

	public function init() {
        // COMENTADO PARA ATIVAR HTTS EM TODO O AGRONET NÃO APENAS NO LOGIN
		//$this->getHelper('RequireSSL')->setHttps();
		$this->getHelper('layout')->setLayout('no-layout');
		$this->view->headTitle('Área Restrita');
        $this->ambienteProducao = APPLICATION_ENV === 'production';

        if (!$this->ambienteProducao) {
            $this->protocoloUrlNovaSenha = 'http://';
            $this->urlNovaSenha = $_SERVER['HTTP_HOST'];
        }
	}

	public function indexAction() {
		$Auth = Zend_Auth::getInstance();
		$User = $Auth->getIdentity();

        if (!$User) {
        	if ($this->getRequest()->isPost()) {
        		$f = new Zend_Filter_StripTags();
        		$username = $f->filter($this->getRequest()->getPost('usuario'));
        		$password = $f->filter($this->getRequest()->getPost('senha'));
                $mensagemUsuarioInvalido = 'Usuário e/ou senha inválidos. Uma mensagem foi enviada para o e-mail';
                $mensagemUsuarioInvalido .= ' cadastrado no AgroNet.';

                if ((APPLICATION_ENV === 'production') && ($username !== 'ti.agronet')) {
                    $recaptchaResponse = null;
                
                    if (!empty($this->getRequest()->getPost('g-recaptcha-response'))) {
                        $recaptchaEnterprise = new RecaptchaEnterprise();
                        $recaptchaResponse = $recaptchaEnterprise->createAssessment(
                            $this->getRequest()->getPost('g-recaptcha-response'),
                            'submit'
                        );
                    }
                            
                    if ($recaptchaResponse === null || !$recaptchaResponse->success) {
                        $this->view->msg = 'Erro na verificação do reCaptcha, por favor tente novamente.';
                        return false;
                    }
                }
                
        		if (empty($username) || empty($password)) {
        			$this->view->msg = 'Usuário e senha são obrigatórios.';
        		} else {
        			$Adapter = new Agro_Db_Table_Adapter_Auth();
                    $modelUsuarios = new Sistema_Model_Usuarios();
                    $usuario = $modelUsuarios->fetchRow("ds_nome_usuario = '{$username}'");

                    if ($usuario === null) {
                        $this->view->msg = $mensagemUsuarioInvalido;
                        return false;
                    }

                    if ($usuario->nr_tentativas_acesso >= 3) {
                        $this->usuarioExcedeuTentativasAcesso($usuario);
                        $this->view->msg = $mensagemUsuarioInvalido;
                        return false;
                    }

                    if (!$usuario->fl_ativo) {
                        $this->view->msg = $mensagemUsuarioInvalido;
                        $this->enviarEmailExcecoesUsuario($usuario, 1);

                        return false;
                    }

                    if ($usuario->fl_bloqueio_inatividade) {
                        $this->view->msg = $mensagemUsuarioInvalido;
                        $this->enviarEmailExcecoesUsuario($usuario, 2);

                        return false;
                    }

                    $dataAtual = new DateTime('now');
                    $dataExpiracaoSenha = new DateTime($usuario->dt_expiracao_senha);

                    if ($dataAtual > $dataExpiracaoSenha) {
                        $this->view->msg = $mensagemUsuarioInvalido;
                        $this->enviarEmailExcecoesUsuario($usuario, 3);

                        return false;
                    }

        			// Define quais os campos serão usados na autenticação
        			$Adapter->setTableName('sistema.v_login');
        			$Adapter->setIdentityColumn('ds_nome_usuario');
        			$Adapter->setCredentialColumn('ds_senha');

        			// Seta os valores nos campos de autenticação
        			$Adapter->setIdentity($username);
                    $Adapter->setCredential($password);

                    $useragent         = $_SERVER['HTTP_USER_AGENT'];
                    $flBloquearBrowser = false;

                    //Liberado apenas qualquer versão do Navegador Firefox ou Chrome.
                    if(preg_match('/(Chrome|Firefox)\/([0-9\.]+)/',$useragent,$matched)) {
                        $browser_version=$matched[1];
                        $browser = 'Firefox';
                        $flBloquearBrowser = false;
                    } else {
                        $browser_version = 0;
                        $browser= 'other';
                        $flBloquearBrowser = true;
                    }

                    if (APPLICATION_ENV != 'production') {
                    	$flBloquearBrowser = false;
                    }

                    if($flBloquearBrowser == true){
                        $this->view->msg = 'O navegador utilizado não está homologado para acessar o Agronet 2.0.\n\nPara o correto funcionamento do sistema recomendamos a utilização do navegador Mozilla Firefox.';
                    } else {
    					if ($Auth->authenticate($Adapter)->isValid()) {
    						$data = $Adapter->getResultRowObject(null,'ds_senha');

    						if (!$data->fl_ativo) {
    							$this->view->msg = 'Erro na autenticação.\n\nFavor contatar o administrador do sistema.';
    							Zend_Auth::getInstance()->clearIdentity();
    						} else {
    							$Role = new Sistema_Model_Roles();
    							$Row = $Role->find($data->id_role)->current();
    							$data->ds_chave = $Row->ds_chave;

    							$Acl = Agro_Acl::getInstance($data);
    							$data->Acl = $Acl;

    							$LogAcesso = new Log_Model_Acesso();
    							$LogAcesso->save(array('id_usuario' => $data->id, 'tipo' => 'login'));

    							/**
    							 * Busca o usuário para limpar o hash de url da senha
    							 */
                                $usuario = $modelUsuarios->fetchRow("id = $data->id");
                                $usuario->ds_url_senha = '';
                                $usuario->nr_tentativas_acesso = 0;
                                $usuario->save();

    							$Auth->getStorage()->write($data);
    							$this->_redirect('/agronet');
    						}
    					} else {
                            if ($usuario === null) {
                                $mensagemErro = $mensagemUsuarioInvalido;
                            }

                            if ($usuario !== null) {
                                $mensagemErro = $mensagemUsuarioInvalido;

                                if ($usuario->nr_tentativas_acesso >= 3) {
                                    $this->usuarioExcedeuTentativasAcesso($usuario);
                                } else {
                                    $this->enviarEmailExcecoesUsuario($usuario, 6);
                                }

                                $usuario->nr_tentativas_acesso++;
                                $usuario->save();
                            }

    						$this->view->msg = $mensagemErro;
    					}
                    }
				}
			}
		} else {
			$this->_redirect('/agronet');
		}
	}

    public function getpasswordAction()
    {
        $user = pg_escape_string(trim($this->getRequest()->getParam('usuario')));
        $this->view->ambienteProducao = $this->ambienteProducao;
        $classTipoErro = [
            0 => 'msg_erro',
            1 => 'msg',
        ];

        if ($this->getRequest()->isPost()) {
            try {
                if ($this->ambienteProducao) {
                    $recaptchaResponse = null;
                
                    if (!empty($this->getRequest()->getPost('g-recaptcha-response'))) {
                        $recaptchaEnterprise = new RecaptchaEnterprise();
                        $recaptchaResponse = $recaptchaEnterprise->createAssessment(
                            $this->getRequest()->getPost('g-recaptcha-response'),
                            'submit'
                        );
                    }

                    if ($recaptchaResponse === null || !$recaptchaResponse->success) {
                        throw new Exception('Erro na verificação do reCaptcha, por favor tente novamente.');
                    }
                }

                if (empty($user)) {
                    throw new Exception('Informe um usuário para realizar a recuperação da senha.');
                }

                $mensagemResposta = 'Uma mensagem foi enviada para o e-mail cadastrado no AgroNet, contendo as';
                $mensagemResposta .= ' informações sobre sua solicitação de senha.';
                $usuario = (new Sistema_Model_Usuarios())->fetchRow("ds_nome_usuario = '{$user}'");

                if (empty($usuario)) {
                    throw new Exception($mensagemResposta, 1);
                }

                if (!$usuario->fl_ativo) {
                    $this->enviarEmailExcecoesUsuario($usuario, 1);
                    throw new Exception($mensagemResposta, 1);
                }

                if (!empty($usuario->dt_expiracao_url_senha)) {
                    if (date('d') === date('d', strtotime($usuario->dt_expiracao_url_senha))) {
                        $dataAtual = new DateTime('now');
                        $dataExpiracaoSalva = new DateTime($usuario->dt_expiracao_url_senha);
                        $diferenca = $dataAtual->diff($dataExpiracaoSalva);

                        if ($diferenca->h === 0 && $diferenca->i <= 15) {
                            $this->enviarEmailExcecoesUsuario($usuario, 4);
                            throw new Exception($mensagemResposta, 1);
                        }

                        if ((int)$usuario->nr_solicitacoes_troca_senha >= 3) {
                            $this->enviarEmailExcecoesUsuario($usuario, 5);
                            throw new Exception($mensagemResposta, 1);
                        }
                    } else {
                        $usuario->nr_solicitacoes_troca_senha = 0;
                    }
                }

                $hash = $this->gerarHashLinkSenha();
                $usuario->ds_url_senha = $hash;
                $usuario->dt_expiracao_url_senha = date('Y-m-d H:i:s');
                $usuario->nr_solicitacoes_troca_senha = (int)$usuario->nr_solicitacoes_troca_senha + 1;

                if (!$usuario->save()) {
                    throw new Exception('Erro ao atualizar informações do usuário.');
                }

                $this->view->usuario = $usuario->login();
                $this->view->link = "{$this->protocoloUrlNovaSenha}{$this->urlNovaSenha}{$this->parametrosUrlNovaSenha}";
                $this->view->link .= "{$hash}";
                $content = $this->view->render('forgot_pass.phtml');

                if ($usuario->tp_usuario == 'P') {
                    $Prepostos = new Sistema_Model_Prepostos();
                    $corretor = $Prepostos->getCorretorByUsuario($usuario->id);
                    $this->view->usuario->ds_email = $corretor->ds_email;
                }

                if ($usuario->tp_usuario != Sistema_Model_Usuarios::TIPO_USUARIO_HELPER) {
                    $this->enviarEmail(
                        $content,
                        $this->view->usuario->ds_email,
                        'Dados de Acesso ao AgroNet 2.0',
                        true
                    );
                }

                $this->view->msg = $mensagemResposta;
                $this->view->class = 'msg';
            } catch (Exception $e) {
                $this->view->msg = $e->getMessage();
                $this->view->class = $classTipoErro[$e->getCode()];
            }
        }
    }

	public function logoutAction () {
		$Session = new Zend_Session_Namespace('variaveis');
		$Session->unsetAll();

		Zend_Auth::getInstance()->clearIdentity();
		$_SESSION['menu'] = '';
		$this->_redirect('/login');
	}

    public function novasenhaAction()
    {
        $hash = $this->getRequest()->getParam('url');
        $this->view->urlInvalida = false;
        $this->view->senha1 = '';
        $this->view->senha2 = '';
        $mensagemUrlInvalida = 'URL inválida ou expirada. Clique abaixo em Solicitar Nova Senha.';

        $modelUsuarios = new Sistema_Model_Usuarios();
        $modelUsuarioHistoricoSenha = new Sistema_Model_UsuarioHistoricoSenha();

        $usuario = $modelUsuarios->fetchRow("ds_url_senha = '{$hash}'");

        if ($usuario === null) {
            $this->view->urlInvalida = true;
            $this->view->mensagem = $mensagemUrlInvalida;
        }

        if (!empty($usuario->dt_expiracao_url_senha)) {
            $dataAtual = new DateTime('now');
            $dataExpiracaoSalva = new DateTime($usuario->dt_expiracao_url_senha);
            $diferenca = $dataAtual->diff($dataExpiracaoSalva);

            if ($diferenca->days > 1) {
                $this->view->urlInvalida = true;
                $this->view->mensagem = $mensagemUrlInvalida;
            }

            if ($diferenca->days === 0) {
                if ($diferenca->h > 1 || ($diferenca->h === 1 && $diferenca->i > 0)) {
                    $this->view->urlInvalida = true;
                    $this->view->mensagem = $mensagemUrlInvalida;
                }
            }
        }

        if ($this->getRequest()->isPost()) {
            $agroSenha = new Agro_Senha();

            if (!empty($this->getRequest()->getParam('sugestaoSenha'))) {
                $this->view->senha1 = $this->view->senha2 = $agroSenha->gerarNovaSenha();
            }

            if (!empty($this->getRequest()->getParam('salvar'))) {
                try {
                    $parametros = $this->getRequest()->getParams();
                    $this->view->senha1 = $parametros['senha1'];
                    $this->view->senha2 = $parametros['senha2'];
                    $senhaValida = $agroSenha->validarSenha($parametros['senha1'], $parametros['senha2']);

                    if (!$senhaValida) {
                        throw new Exception($agroSenha->retornarMensagemErros());
                    }

                    $senhaCriptograda = password_hash($parametros['senha1'], PASSWORD_BCRYPT);

                    if (!$modelUsuarioHistoricoSenha->podeUsarSenha($usuario->id, $parametros['senha1'])) {
                        throw new Exception('Não é possível cadastrar uma senha utilizada anteriormente.');
                    }

                    $dataExpiracaoSenha = new DateTime('now');
                    $dataExpiracaoSenha->add(new DateInterval('P4M'));

                    $usuario->ds_url_senha = '';
                    $usuario->ds_senha = $senhaCriptograda;
                    $usuario->nr_tentativas_acesso = 0;
                    $usuario->dt_expiracao_senha = $dataExpiracaoSenha->format('Y-m-d H:i:s');
                    $usuario->fl_notificado_expiracao_senha = 0;
                    $usuario->fl_notificado_bloqueio_inatividade = 0;
                    $usuario->fl_bloqueio_inatividade = 0;
                    $usuario->dt_expiracao_url_senha = null;
                    $usuario->nr_solicitacoes_troca_senha = 0;
                    $usuario->save();

                    $modelUsuarioHistoricoSenha->save($usuario->id, $senhaCriptograda, 2068);

                    $this->_redirect('/login');
                } catch (Exception $erro) {
                    $this->view->mensagem = $erro->getMessage();
                }
            }
        }
    }

    private function gerarHashLinkSenha() : string
    {
        $agroSenha = new Agro_Senha();
        return $agroSenha->gerarHash();
    }

    private function enviarEmail(
        string $conteudo,
        string $destinatario,
        string $assunto,
        bool $enviarParaDestinatarioAmbienteTeste = false,
        bool $inicioTextoPadrao = false
    ) : void
    {
        $mail = new Agro_Mail();
        $mail->inicioTextoPadrao($inicioTextoPadrao);
        $mail->setBody($conteudo);
        $mail->addTo($destinatario);
        $mail->setSubject($assunto);
        $mail->enviarParaDestinatarioAmbienteTeste($enviarParaDestinatarioAmbienteTeste);
        $mail->send();
    }

    private function usuarioExcedeuTentativasAcesso($usuario)
    {
        $hash = $this->gerarHashLinkSenha();
        $usuario->ds_url_senha = $hash;

        $this->view->usuario = $usuario->login();
        $this->view->link = "{$this->protocoloUrlNovaSenha}{$this->urlNovaSenha}/login/getpassword";
        $conteudo = $this->view->render('usuario_bloqueado.phtml');

        if ($usuario->tp_usuario == 'P') {
            $Prepostos = new Sistema_Model_Prepostos();
            $corretor = $Prepostos->getCorretorByUsuario($usuario->id);
            $this->view->usuario->ds_email = $corretor->ds_email;
        }

        try {
            if ($usuario->tp_usuario != Sistema_Model_Usuarios::TIPO_USUARIO_HELPER) {
                $this->enviarEmail(
                    $conteudo,
                    $this->view->usuario->ds_email,
                    'Suspeita de Acesso Indevido ao Agronet 2.0',
                    true
                );
            }
        } catch (Exception $e) {
            $this->view->msg = $e->getMessage();
        }

        $usuario->save();
    }

    private function enviarEmailExcecoesUsuario($usuario, int $excecao)
    {
        switch ($excecao) {
            case 1:
                $arquivo = 'usuario_inativo.phtml';
                break;
            case 2:
                $arquivo = 'usuario_bloqueio_inatividade.phtml';
                break;
            case 3:
                $arquivo = 'usuario_senha_expirada.phtml';
                break;
            case 4:
                $arquivo = 'link_senha_enviado.phtml';
                break;
            case 5:
                $arquivo = 'limite_excedido_link.phtml';
                break;
            case 6:
                $arquivo = 'tentiva_acesso.phtml';
                break;
        }

        $rowCadastro = (new Sistema_Service_Usuarios())
            ->getDadosCadastroByTipo($usuario->tp_usuario, (int)$usuario->id);

        if (
            !empty($rowCadastro)
            && !empty($rowCadastro['ds_email'])
            && $usuario->tp_usuario != Sistema_Model_Usuarios::TIPO_USUARIO_HELPER
        ) {
            $this->view->linkSenha = "{$this->protocoloUrlNovaSenha}{$this->urlNovaSenha}";
            $this->view->linkSenha .= "/login/getpassword";

            $this->enviarEmail(
                $this->view->render($arquivo),
                $rowCadastro['ds_email'],
                'Acesso ao AgroNet 2.0',
                false,
                true
            );
        }
    }
}
