<?php

class Sistema_UsuarioController extends Agro_Controller_Action
{
    private $modelAcao;

    public function init()
    {
        parent::init();

        $this->modelAcao = new Sistema_Model_Acoes();
    }

    public function getModel()
    {
        return new Sistema_Model_Usuarios();
    }

    public function permissoesAction()
    {
        $this->getHelper('layout')->disableLayout();

        $model = new Sistema_Model_Acoes();
        $id = !Agro_Util::filterVariable($this->getRequest()->getParam('id'))
            ? 0
            : (int)$this->getRequest()->getParam('id');

        $this->view->id_usuario = $id;
        $this->view->checked = array();

        if (!empty($id)) {
            $user = (new Sistema_Model_Usuarios())->find($id)->current();
            $acoes = $model->fetchAll("fl_del = 'f'")->toArray();

            foreach ($acoes as $acao) {
                if ($model->checkRoleAllowed((int)$user->id_role, (int)$acao["id"])) {
                    $this->view->checked[] = $acao["id"];
                }
            }

            foreach ($model->getUserExcecao($user->id) as $acao) {
                if ($acao->fl_permitido) {
                    if (!in_array($acao->id_acao, $this->view->checked)) {
                        $this->view->checked[] = $acao->id_acao;
                    }
                } else {
                    //valida a os filhos para não retirar os pais caso haja algum outro filho marcado
                    if (
                        in_array($acao->id_acao, $this->view->checked)
                        && !$this->temFilhoPermitido($user, $acao->id_acao)
                    ) {
                        unset($this->view->checked[array_search($acao->id_acao, $this->view->checked)]);
                    }
                }
            }
        }
    }

    private function temFilhoPermitido($user, $idAcao)
    {
        $filhos = $this->modelAcao->getFilhos($idAcao);

        foreach ($filhos as $filho) {
            if (
                $this->modelAcao->checkUserAllowedWithException($user->id, $filho['id'])
                && $this->modelAcao->checkRoleAllowed((int)$user->id_role, (int)$filho['id'])
            ) {
                return true;
            } else {
                $result = $this->temFilhoPermitido($user, $filho['id']);
                if ($result) {
                    return $result;
                }
            }
        }

        return false;
    }

    public function setpermissoesAction()
    {
        $this->isAjax();

        $excecaoUsuario = new Sistema_Model_ExcecaoUsuario();

        Zend_Db_Table::getDefaultAdapter()->beginTransaction();

        try {
            $params = $this->getRequest()->getParams();

            $excecaoUsuario->getDefaultAdapter()->query("delete from sistema.usuarios_acao where id_usuario = {$params["id_usuario"]}");

            if ($excecaoUsuario->canSave($params)) {
                $modelUsuarios = new Sistema_Model_Usuarios();
                $rowUsuario = $modelUsuarios->getRow($params["id_usuario"]);

                $modelRolesAcao = new Sistema_Model_RolesAcao();
                $arrayRolesAcao = $modelRolesAcao->fetchAll("id_role = {$rowUsuario['id_role']}")->toArray();
                $acoesSalvar = ['id_usuario' => $params["id_usuario"]];

                foreach ($arrayRolesAcao as $indice => $roleAcao) {
                    /**
                     * Valida ações em comum (permitidas) no perfil e usuário, removendo do array $params['id_acao']
                     */
                    if (in_array($roleAcao['id_acao'], $params['id_acao'])) {
                        $indiceParams = array_search($roleAcao['id_acao'], $params['id_acao']);
                        unset($params['id_acao'][$indiceParams]);

                        continue;
                    }

                    /**
                     * Valida ações que estão no perfil, mas que foram desmarcadas no usuário. Neste caso, deve salvar
                     * em usuarios_acao como fl_permitido = false
                     */
                    if (!in_array($roleAcao['id_acao'], $params['id_acao'])) {
                        $acoesSalvar['id_acao']['nao_permitido'][] = $roleAcao['id_acao'];

                        continue;
                    }
                }

                /**
                 * Percorre as ações do usuário que foram marcadas e não são permitidas no perfil. Neste caso, deve salvar
                 * em usuarios_acao como fl_permitido = true
                 */
                foreach ($params['id_acao'] as $acao) {
                    $acoesSalvar['id_acao']['permitido'][] = $acao;
                }

                if ($rowUsuario['tp_usuario'] === Sistema_Model_Usuarios::TIPO_USUARIO_PREPOSTO) {
                    $modelPrepostos = new Sistema_Model_Prepostos();
                    $rowPreposto = $modelPrepostos->findByUser($params["id_usuario"]);

                    if (!empty($rowPreposto) && !empty(trim($rowPreposto['ds_excecoes']))) {
                        $excecoes = explode(',', $rowPreposto['ds_excecoes']);

                        foreach ($excecoes as $excecao) {
                            if ($excecao === '2') {
                                continue;
                            }

                            $acoesSalvar['id_acao']['nao_permitido'] = array_merge(
                              $acoesSalvar['id_acao']['nao_permitido'], Sistema_Model_ExcecaoUsuario::$_RESTRICOES_PREPOSTO[trim($excecao)]
                            );
                        }
                    }
                }

                $excecaoUsuario->setBloqueioAcao($acoesSalvar);

                Zend_Db_Table::getDefaultAdapter()->commit();
                $result = array("status" => true, "message" => "Exceções atribuidas com sucesso.");
            } else {
                Zend_Db_Table::getDefaultAdapter()->rollBack();
                Agro_Util::informaErroAgronet($excecaoUsuario->getMessages());
                $result = array("status" => false, "message" => "Não foi possível atribuir exceções ao usuário.");
            }
        } catch (Zend_Exception $ze) {
            Zend_Db_Table::getDefaultAdapter()->rollBack();
            if ($ze->getCode() == 1) {
                $result = array("status" => false, "message" => $ze->getMessage());
            } else {
                $result = array("status" => false, "message" => "Não foi possível atribuir exceções ao usuário.");
            }
        } catch (Exception $e) {
            Zend_Db_Table::getDefaultAdapter()->rollBack();
            Agro_Util::informaErroAgronet($e->getMessage());
            $result = array("status" => false, "message" => "Não foi possível atribuir exceções ao usuário.");
        }

        $this->getResponse()->setBody(Zend_Json::encode($result));
    }

    public function gettipousuarioAction()
    {
        $this->getHelper('ViewRenderer')->setNoRender();
        $this->getHelper('layout')->disableLayout();
        $User = Zend_Auth::getInstance()->getIdentity();
        $Empresas = new Sistema_Model_Empresas();
        $Empresa = $Empresas->getIdEmpresaUsuarioCorrente();
        $usuario['tipo'] = $User->tp_usuario;
        $usuario['empresa'] = $Empresa;
        $this->getResponse()->setBody(Zend_Json::encode($usuario));
    }

    public function usuariosbyempresaAction()
    {
        $result = array();
        $result['usuarios'] = null;

        $this->isAjax();

        if ($this->getRequest()->getParam('id_empresa')) {
            $Usuario = new Sistema_Model_Usuarios();
            $usuarios = $Usuario->getUsuariosByEmpresaMobile($this->getRequest()->getParam('id_empresa'));
            $result['usuarios'] = $usuarios;
            $result['status_message'] = 'OK';
        } else {
            $result['status_message'] = 'Parâmetros insuficientes para execução.';
        }

        $this->getResponse()->setBody(Zend_Json::encode($result));
    }

    public function limpardispositivoAction()
    {
        $retorno = ['sucesso' => true, 'mensagem' => 'Operação realizada com sucesso.'];
        Zend_Db_Table::getDefaultAdapter()->beginTransaction();

        $this->isAjax();

        try {
            $usuarioModel = new Sistema_Model_Usuarios();

            if ($this->getRequest()->getParam('tipo') == 2) {
                $usuarioModel->atualizarDispositivoSinistro($this->getRequest()->getParam('id_usuario'));

                $modelLogAlteracaoDeviceSinistro = new Log_Model_LogAlteracaoDeviceSinistro();
                $modelLogAlteracaoDeviceSinistro->save($this->getRequest()->getParams());
            } else {
                $usuarioModel->atualizarDispositivoPrevia($this->getRequest()->getParam('id_usuario'));

                $logAlteracaoDeviceVpModel = new Log_Model_LogAlteracaoDeviceVP();
                $logAlteracaoDeviceVpModel->save($this->getRequest()->getParams());
            }

            Zend_Db_Table::getDefaultAdapter()->commit();
        } catch (Exception $erro) {
            $retorno['sucesso'] = false;
            $retorno['mensagem'] = 'Erro ao limpar o dispositivo.';

            Zend_Db_Table::getDefaultAdapter()->rollBack();
        }

        $this->getResponse()->setBody(Zend_Json::encode($retorno));
    }

    public function gerarsenhaAction()
    {
        $this->isAjax();
        $this->getResponse()->setBody(Zend_Json::encode(['senha' => (new Agro_Senha())->gerarNovaSenha()]));
    }

    public function gettodosusuariosativosAction()
    {
        $this->isAjax();

        $retorno = [];
        $rowsUsuario = $this->getModel()->getUser(false, true);

        foreach ($rowsUsuario as $rowUsuario) {
            $dadosUsuario = new stdClass();
            $dadosUsuario->id = $rowUsuario['id'];
            $dadosUsuario->ds_nome_usuario = $rowUsuario['ds_nome_usuario'];

            $retorno[] = $dadosUsuario;
        }

        $this->getResponse()->setBody(Zend_Json::encode($retorno));
    }

    public function liberaracaousuarioAction()
    {
        $this->isAjax();

        $this->_return['mensagem'] = 'Configurações salvas com sucesso';
        $adapter = Zend_Db_Table::getDefaultAdapter();

        try {
            $adapter->beginTransaction();

            $modelUsuarioAcao = new Sistema_Model_UsuarioAcao();

            if (!$modelUsuarioAcao->deletarByUsuarioAcao((int) $this->_requestParams['id_usuario'], (int) $this->_requestParams['id_acao'])) {
                throw new Exception('Erro ao remover a ação.');
            }

            if ((bool) $this->_requestParams['liberar'] === true) {
                $dados = [
                    'id_usuario' => $this->_requestParams['id_usuario'],
                    'id_acao' => $this->_requestParams['id_acao'],
                ];

                if (!$modelUsuarioAcao->insert($dados)) {
                    throw new Exception('Erro ao liberar a ação.');
                }
            }

            $adapter->commit();
        } catch (Exception $erro) {
            $adapter->rollBack();
            $this->_return['erro'] = true;
            $this->_return['mensagem'] = $erro->getMessage();
        }

        $this->getResponse()->setBody(Zend_Json::encode($this->_return));
    }

    public function verificaexpiracaosenhaAction(): void
    {
        $this->isAjax();

        $modelUsuarios = new Sistema_Model_Usuarios();
        $adapter = Zend_Db_Table::getDefaultAdapter();

        try {
            $adapter->beginTransaction();

            $usuarios = $modelUsuarios->getSenhasExpiradasOuPrestesAExpirar();
            $idsUsuariosNotificar = [];
            $usuariosAgrupados = [];
            $codigoAgrupamentoNaoSublogins = 0;

            foreach ($usuarios as $usuario) {
                if ($usuario['id_agrupamento'] !== $codigoAgrupamentoNaoSublogins) {
                    $usuariosAgrupados[$usuario['id_agrupamento']][] = $usuario;
                    continue;
                }

                if ($this->usuarioDeveReceberNotificacaoEmail($usuario)) {
                    $dias = (int)$usuario['expira_em'];

                    $this->enviaEmailBloqueioInativacao(
                        $usuario,
                        'EXPIRAÇÃO DE SENHA AGRONET',
                        "Sua senha expira em {$dias} dia(s). Por favor, redefina sua senha."
                    );

                    $idsUsuariosNotificar[] = $usuario['id'];
                }
            }

            foreach ($usuariosAgrupados as $usuarios) {
                $infoUsuario = [];
                $mensagem = "A senha dos seguintes usuários está prestes a expirar:<br>";

                foreach ($usuarios as $usuario) {
                    if ($this->usuarioDeveReceberNotificacaoEmail($usuario)) {
                        $infoUsuario['ds_nome_preposto'] = $usuario['ds_nome_corretor_preposto'];
                        $infoUsuario['ds_email_preposto'] = $usuario['ds_email_corretor_preposto'];

                        $dias = (int)$usuario['expira_em'];
                        $mensagem .= "- {$usuario['ds_nome_preposto']}: {$dias} dia(s)<br>";
                        $idsUsuariosNotificar[] = $usuario['id'];
                    }
                }

                $mensagem .= "<br>Por favor, redefina as senhas.";

                if (!empty($infoUsuario)) {
                    $this->enviaEmailBloqueioInativacao(
                        $infoUsuario,
                        'EXPIRAÇÃO DE SENHA AGRONET',
                        $mensagem
                    );
                }
            }

            if (!empty($idsUsuariosNotificar)) {
                $modelUsuarios->update(
                    ['fl_notificado_expiracao_senha' => 1],
                    "id IN (" . implode(',', $idsUsuariosNotificar) . ")"
                );
            }

            $adapter->commit();

            $this->getResponse()->setBody(Zend_Json::encode(
                [
                    'message' => 'Usuários com os seguintes IDs foram notificados: ' . implode(',', $idsUsuariosNotificar),
                    'statusCode' => 200
                ]
            ));
        } catch (Exception $e) {
            $adapter->rollback();

            $this->getResponse()->setBody(Zend_Json::encode(
                [
                    'message' => $e->getMessage(),
                    'statusCode' => 406
                ]
            ));
        }
    }

    public function bloqueiausuarioinativoAction(): void
    {
        $this->isAjax();

        $modelUsuarios = new Sistema_Model_Usuarios();
        $adapter = Zend_Db_Table::getDefaultAdapter();

        try {
            $adapter->beginTransaction();

            $usuarios = $modelUsuarios->getUsuariosMesesInativo();
            $idsUsuarioInativar = $separatorInativar = '';
            $idsUsuarioNotificar = $separatorNotificar = '';

            $dataAtual = new DateTime('now');

            $usuariosAgrupados = [];
            $codigoAgrupamentoNaoSublogins = 0;

            foreach ($usuarios as $usuario) {
                $dataBloqueio = new DateTime($usuario['data_acesso']);
                $dataBloqueio->add(new DateInterval('P6M'));

                $intervalo = $dataBloqueio->diff($dataAtual);

                // Bloqueia
                if ($usuario['meses_inativo'] >= 6 || $intervalo->days == 0) {
                    $idsUsuarioInativar .= "{$separatorInativar}{$usuario['id']}";
                    $separatorInativar = ', ';

                    $usuario['status'] = 'bloquear';
                    $usuario['dias'] = '';
                    $usuariosAgrupados[$usuario['id_agrupamento']][] = $usuario;

                    continue;
                }

                if (
                    $usuario['meses_inativo'] == 5
                    && (!$usuario['fl_notificado_bloqueio_inatividade'] || $intervalo->days <= 5)
                ) {
                    $idsUsuarioNotificar .= "{$separatorNotificar} {$usuario['id']}";
                    $separatorNotificar = ', ';

                    $usuario['status'] = 'notificar';
                    $usuario['dias'] = $intervalo->days;
                    $usuariosAgrupados[$usuario['id_agrupamento']][] = $usuario;
                }
            }

            foreach ($usuariosAgrupados[$codigoAgrupamentoNaoSublogins] as $usuario) {
                if ($usuario['status'] === 'bloquear') {
                    $this->enviaEmailBloqueioInativacao(
                        $usuario,
                        'BLOQUEIO POR INATIVIDADE AGRONET',
                        "Seu acesso ao Agronet foi bloqueado por inatividade."
                    );
                }

                if ($usuario['status'] === 'notificar') {
                    $this->enviaEmailBloqueioInativacao(
                        $usuario,
                        'BLOQUEIO POR INATIVIDADE AGRONET',
                        "Seu acesso será bloqueado em um prazo de {$usuario['dias']} dia(s) por inatividade."
                    );
                }
            }

            unset($usuariosAgrupados[$codigoAgrupamentoNaoSublogins]);

            foreach ($usuariosAgrupados as $usuarios) {
                $infoUsuario = [];
                $mensagemBloqueio = "O acesso ao Agronet, dos usuários abaixo, foi bloqueado por inatividade:<br>";
                $mensagemBloqueioFuturo = "O acesso ao Agronet, dos usuários abaixo, será bloqueado por inatividade";
                $mensagemBloqueioFuturo .= " dentro do prazo informado para cada um:<br>";

                foreach ($usuarios as $usuario) {
                    $infoUsuario['ds_nome_preposto'] = $usuario['ds_nome_corretor_preposto'];
                    $infoUsuario['ds_email_preposto'] = $usuario['ds_email_corretor_preposto'];
                    $infoUsuario['status'] = $usuario['status'];

                    if ($usuario['status'] === 'notificar') {
                        $mensagemBloqueioFuturo .= "- {$usuario['ds_nome_usuario']}: {$usuario['dias']} dia(s)<br>";
                    } else {
                        $mensagemBloqueio .= "- {$usuario['ds_nome_usuario']}<br>";
                    }
                }

                if (!empty($infoUsuario)) {
                    if ($infoUsuario['status'] === 'bloquear') {
                        $this->enviaEmailBloqueioInativacao(
                            $infoUsuario,
                            'BLOQUEIO POR INATIVIDADE AGRONET',
                            $mensagemBloqueio
                        );
                    }

                    if ($infoUsuario['status'] === 'notificar') {
                        $this->enviaEmailBloqueioInativacao(
                            $infoUsuario,
                            'BLOQUEIO POR INATIVIDADE AGRONET',
                            $mensagemBloqueioFuturo
                        );
                    }
                }
            }

            if (!empty($idsUsuarioInativar)) {
                $modelUsuarios->update(
                    ['fl_bloqueio_inatividade' => 1],
                    "id IN ({$idsUsuarioInativar})"
                );
            }

            if (!empty($idsUsuarioNotificar) || !empty($idsUsuarioInativar)) {
                $modelUsuarios->update(
                    ['fl_notificado_bloqueio_inatividade' => 1],
                    "id IN ({$idsUsuarioNotificar})"
                );
            }

            $adapter->commit();

            $this->getResponse()->setBody(Zend_Json::encode(
                [
                    'message' =>
                        'Usuários com os seguintes IDs foram notificados: ' . $idsUsuarioNotificar
                        . "\nUsuários com os seguintes IDs foram bloqueados: {$idsUsuarioInativar}",
                    'statusCode' => 200
                ]
            ));
        } catch (Exception $e) {
            $adapter->rollback();

            $this->getResponse()->setBody(Zend_Json::encode(
                [
                    'message' => $e->getMessage(),
                    'statusCode' => 406
                ]
            ));
        }
    }

    private function enviaEmailBloqueioInativacao(array $infoUsuario, string $assunto, string $mensagem): void
    {
        $email = $nome = '';

        if (!empty($infoUsuario['ds_email_funcionario'])) {
            $email = $infoUsuario['ds_email_funcionario'];
            $nome = $infoUsuario['ds_nome_funcionario'];
        } elseif (!empty($infoUsuario['ds_email_corretor'])) {
            $email = $infoUsuario['ds_email_corretor'];
            $nome = $infoUsuario['ds_nome_corretor'];
        } elseif (!empty($infoUsuario['ds_email_preposto'])) {
            $email = $infoUsuario['ds_email_preposto'];
            $nome = $infoUsuario['ds_nome_preposto'];
        } elseif (!empty($infoUsuario['ds_email_assessoria'])) {
            $email = $infoUsuario['ds_email_assessoria'];
            $nome = $infoUsuario['ds_nome_assessoria'];
        }

        $nome = Agro_Util::formataNome($nome);

        $body = "Prezado(a) {$nome}.<br><br>{$mensagem}";
        $body .= "<br><br>Acesse o sistema Agronet 2.0 através do endereço: <a href='http://agronet.agrobrasilseguros.com.br/'>http://agronet.agrobrasilseguros.com.br/</a>";
        $body .= "<br>ATENÇÃO: esta é uma mensagem automática. Por favor, não responda. Se deseja entrar em contato conosco, escreva para atendimento@agrobrasilseguros.com.br <br><br>";

        $agroMail = new Agro_Mail();

        $agroMail->addTo($email, $nome);
        $agroMail->setSubject($assunto);
        $agroMail->setBody($body, 'html');
        $agroMail->send();
    }

    private function usuarioDeveReceberNotificacaoEmail(array $usuario)
    {
        return $usuario['expira_em'] > 0 && $usuario['expira_em'] <= 10 && !$usuario['fl_notificado_expiracao_senha'];
    }

    public function autocompleteAction() {
        $this->isAjax();
        $return = (new Sistema_Model_Usuarios())
            ->getComplete($this->getRequest()->getParam('q'));

        $this->getResponse()->setBody(Zend_Json::encode($return));
    }

    public function iscorretorAction()
    {
        $this->isAjax();
        $retorno = ['sucesso' => true, 'mensagem' => '', 'is_corretor' => false];

        try {
            $retorno['is_corretor'] = Sistema_Model_Usuarios::isUsuarioLogadoCorretorPreposto();
        } catch (\Throwable $th) {
            $retorno['sucesso'] = false;
            $retorno['mensagem'] = $th->getMessage();
        }

        $this->getResponse()->setBody(Zend_Json::encode($retorno));
        
    }
}
