<?php

namespace CulturaViva;

use CulturaViva\Importer;
use MapasCulturais\API;
use MapasCulturais\ApiQuery;
use MapasCulturais\App;
use MapasCulturais\Entities\Agent;
use MapasCulturais\Entities\AgentMeta;
use MapasCulturais\Entities\AgentRelation;
use MapasCulturais\Entities\EvaluationMethodConfigurationAgentRelation;
use MapasCulturais\Entities\Opportunity;
use MapasCulturais\Entities\Registration;
use MapasCulturais\Entities\RegistrationEvaluation;
use MapasCulturais\Entities\RegistrationSpaceRelation;
use MapasCulturais\Entities\Space;
use MapasCulturais\i;

class Theme extends \MapasCulturais\Themes\BaseV2\Theme
{

    protected Opportunity $opportunity;

    static function getThemeFolder()
    {
        return __DIR__;
    }

    function _init()
    {
        parent::_init();

        $app = App::i();

        $self = $this;

        $seals = $app->config['rcv.seals'] ?: '0';
        
        $opportunity_id = $app->config['rcv.opportunityId'];

        $this->opportunity = $app->repo('Opportunity')->find($opportunity_id);

        $theme = $this;

        // Restringe exibição de alguns campos via CSS para usuários não administradores
        if(!$app->user->is('admin')){
            $this->bodyClasses[] = 'not-admin';
        }

        // Faz com que o filtro na tabela de agentes so mostre os selos do CulturaViva
        $app->hook('component(agent-table).querySeals', function(&$queryParams) use ($app) {
            $seals = $app->config['rcv.seals'];
            $queryParams['id'] = "IN({$seals})";
        });

        // Ajusta titulo da página do formulário
        $app->hook('mapasculturais.getTitle', function(&$title) use ($app) {
            $entity = $this->controller->requestedEntity;
            if($entity && get_class($entity) == Registration::class) {
                $title = $entity->opportunity->name . " - " . $app->siteName;
            }
        });

        // Adiciona links para lista de inscrições e de avaliações no painel de controle
        $app->hook('template(panel.index.header-user-button):after', function() use ($app) {
            $opportunity = $app->repo('Opportunity')->find($app->config['rcv.opportunityId']);
            if ($app->user->is('admin') || $opportunity->canUser('@control')) {
                $this->part('registration-links');
            }
        });

        // Bloqeuia campos @ do agente coletivo que são retornados da API da receita
        $app->hook("<<GET|POST|PATCH|PUT>>(registration.<<*>>):before", function () use ($app) {
            $entity = $this->requestedEntity;

            /** @var array */
            $locked_fields = $entity->rcv_locked_fields ?: [];

            $app->hook('mapas.printJsObject:before', function() use ($app, $entity, $locked_fields) {
                $registered_metadadta = $entity->getRegisteredMetadata();
                foreach($registered_metadadta as $field => $def) {
                    $rfc = $def->config['registrationFieldConfiguration'] ?? null;
                    if($rfc && $rfc->fieldType === 'agent-collective-field' && $rfc->config) {
                        $_field = $rfc->config['entityField'];
                        if(in_array($_field, $locked_fields)) {
                            $this->jsObject['EntitiesDescription']['registration'][$field]['readonly'] = true;
                        }
                    }
                   
                }

                if($this->controller->id == 'registration' && $this->controller->action == 'view') {
                    $opportunity = $entity->opportunity;

                    $opportunities_ids = [
                        $app->config['rcv.opportunityId'],
                        $app->config['rcv.pnabOpportunityId']
                    ];

                    if(in_array($opportunity->id, $opportunities_ids)) {
                        $this->breadcrumb = array_values(array_filter($this->breadcrumb, function ($item) {
                            return $item['label'] !== "Oportunidades";
                        }));
                    }
                }
            });
        },10000);


        // Oculta o campo tipo de proponente do CARD de inscrição
        $app->hook("component(registration-card):before", function () use ($app) {
            $app->config['app.registrationCardFields']['proponentType'] = false;
        });

        // Oculta o campo Tipo de Agente do card Meus Agentes no painel
        $app->hook("component(registration-card):before", function () use ($app) {
            $app->config['app.panelEtityCardFields']['type'] = false;
        });

        $app->hook('view.render(site/index):before', function() use($app) {
            $titleTags = ['application-name', 'twitter:title', 'og:title'];

            foreach ($this->documentMeta as &$meta) {
                if ( (isset($meta['name']) && in_array($meta['name'], $titleTags)) || (isset($meta['property']) && in_array($meta['property'], $titleTags)) ) {
                    $meta['content'] = "Rede Cultura Viva";
                }
            }
        });

        $app->hook('view.render(opportunity/single-cadastro):before', function() use($app) {
            $titleTags = ['application-name', 'twitter:title', 'og:title'];

            foreach ($this->documentMeta as &$meta) {
                if ( (isset($meta['name']) && in_array($meta['name'], $titleTags)) || (isset($meta['property']) && in_array($meta['property'], $titleTags)) ) {
                    $meta['content'] = "Cadastro Nacional de Pontos e Pontões de Cultura";
                }
            }
        });

        $app->hook('view.render(panel/registrations):before', function() use($app) {
            
            $app->hook('mapasculturais.getTitle', function (&$title) use ($app) {
                $title = "Cadastros";
            });

            $titleTags = ['application-name', 'twitter:title', 'og:title'];
            foreach ($this->documentMeta as &$meta) {
                if ( (isset($meta['name']) && in_array($meta['name'], $titleTags)) || (isset($meta['property']) && in_array($meta['property'], $titleTags)) ) {
                    $meta['content'] = "Cadastros";
                }
            }
        });

        $app->hook('view.render(search/agent):before', function() use($app) {
            $titleTags = ['application-name', 'twitter:title', 'og:title'];

            foreach ($this->documentMeta as &$meta) {
                if ( (isset($meta['name']) && in_array($meta['name'], $titleTags)) || (isset($meta['property']) && in_array($meta['property'], $titleTags)) ) {
                    $meta['content'] = "Mapa dos Pontos e Pontões de Cultura";
                }
            }

            $app->hook('mapasculturais.getTitle', function() use ($app) {
                foreach ($app->hooks->hookStack as &$stack) {
                    if ($stack->name === 'mapasculturais.getTitle' && $stack->args[0] == "Agentes") {
                        $stack->args[0] = "Mapa dos Pontos e Pontões de Cultura";
                    }
                }
            });
        });

        $app->hook('view.render(search/space):before', function() use($app) {
            $titleTags = ['application-name', 'twitter:title', 'og:title'];

            foreach ($this->documentMeta as &$meta) {
                if ( (isset($meta['name']) && in_array($meta['name'], $titleTags)) || (isset($meta['property']) && in_array($meta['property'], $titleTags)) ) {
                    $meta['content'] = "Espaços dos Pontos e Pontões de Cultura";
                }
            }
        });

        $app->hook('template(agent.single.tabs):end', function() use($app) {
            if($app->config['rcv.disableTabs']) {
                return;
            }

            /** @var \MapasCulturais\Theme $this */
            $this->part('history-tab');
            $this->part('location-tab');
            $this->part('public-tab');
            $this->part('expertise-area-tab');
            $this->part('cultural-economy-tab');
            $this->part('rfb-tab');
        });

        $app->hook("controller(seal).render(sealrelation)", function(&$template, $seal) use ($app) {
            $seals = $app->config['rcv.verificationSeals'];
            
            if ($seal['relation']->seal->id == $seals['ponto']) {
                $template = "certificado-ponto";
            }

            if ($seal['relation']->seal->id == $seals['pontao']) {
                $template = "certificado-pontao";
            }
        });

        //Filtro de inscrições na API
        $app->hook('ApiQuery(Registration).params', function (&$api_params) use($app) {
            /** @var ApiQuery $this */
            
            if($app->config['rcv.disableApiFilters'] || $this->parentQuery) {
                return;
            }

            $opps_id = [$app->config['rcv.opportunityId'], $app->config['rcv.pnabOpportunityId']];
            if(isset($api_params['opportunity'])) {
                $api_params['opportunity'] = API::AND(API::IN($opps_id));
            } else {
                $api_params['opportunity'] = API::IN($opps_id);
            }

        });

        // insere filtro na API para que devolva sempre os selos que estão na lista de selos liberados do CulturaViva
        $app->hook('ApiQuery(Seal).params', function (&$api_params) use($seals, $theme, $app) {
            /** @var ApiQuery $this */

            if($app->config['rcv.disableApiFilters'] || $this->parentQuery || (php_sapi_name() != "cli" && $app->request && $app->request->route == 'GET seal.single')) {
                return;
            }

            $seals_id = $app->config['rcv.seals'];
            $api_params['id'] = API::IN(explode(",", $seals_id));

        });


        $app->hook('ApiQuery(Agent).params', function (&$api_params) use($seals, $theme, $app) {
            /** @var ApiQuery $this */
            
            if($app->config['rcv.disableApiFilters'] || $this->parentQuery) {
                return;
            }
            if (!isset($api_params['type']) && !isset($api_params['id']) && !isset($api_params['parent']) && !isset($api_params['owner']) && !isset($api_params['user'])) {
                $api_params['type'] = API::EQ(2);
            }
        });


        $app->hook('ApiQuery(Agent).joins', function (&$joins) use($seals, $theme, $app) {
            /** @var ApiQuery $this */

            if($app->config['rcv.disableApiFilters'] || $this->parentQuery) {
                return;
            }
            $joins .= "
                LEFT JOIN e.__metadata rcv_tipo 
                    WITH rcv_tipo.key = 'rcv_tipo'";
            
            if(!$theme->canUserControlRCV()) {
                $joins .= "
                    LEFT JOIN e.__sealRelations rcv_sealRelations
                    LEFT JOIN rcv_sealRelations.seal rcv_seal WITH rcv_seal.id IN ($seals)";
            }

            if($app->auth->isUserAuthenticated() && !$app->user->is('admin')) {
                $joins .= " LEFT JOIN e.__permissionsCache rcv_pcache_agent WITH rcv_pcache_agent.action = '@control'";
            }
        });

        $app->hook('ApiQuery(Agent).where', function (&$where) use($theme, $app) {
            /** @var ApiQuery $this */

            if($app->config['rcv.disableApiFilters'] || $this->parentQuery) {
                return;
            }

            $_where = "((e._type = 2 AND rcv_tipo.value = 'ponto') OR e._type = 1)";

            if(!$theme->canUserControlRCV()) {
                $_where .= " AND ((e._type = 2 AND rcv_seal.id IS NOT NULL) OR e._type = 1)";
            }

            if($app->auth->isUserAuthenticated()) {
                if($app->user->is('admin')) {
                    $_where = "e.user = {$app->user->id} OR ($_where)";
                } else {
                    $_where = "rcv_pcache_agent.user = {$app->user->id} OR ($_where)";
                }
            }

            $where .= " AND ({$_where})";
        });

        $app->hook('ApiQuery(Space).params', function (&$api_params) use($seals, $theme, $app) {
            /** @var ApiQuery $this */
            if($app->config['rcv.disableApiFilters']) {
                return;
            }

            // retorna somente espaços de pontos e pontões certificados
            $this->addFilterByApiQuery(new ApiQuery(Agent::class, ['@select' => 'id']), property: 'owner');
        });

        $app->hook('ApiQuery(Space).joins', function (&$joins) use($seals, $theme, $app) {
            if($app->config['rcv.disableApiFilters']) {
                return;
            }
            
            $agent_meta_class = AgentMeta::class;
            $joins .= "
                JOIN e.owner rcv_space_owner
                JOIN $agent_meta_class rcv_space_owner_meta
                    WITH rcv_space_owner_meta.key = 'rcv_sede_spaceId'
                JOIN rcv_space_owner_meta.owner rcv_space_owner_meta_agent 
                    WITH rcv_space_owner_meta_agent.user = rcv_space_owner.user";

            
            if($app->auth->isUserAuthenticated() && !$app->user->is('admin')) {
                $joins .= " 
                    LEFT JOIN e.__permissionsCache rcv_pcache_space 
                        WITH rcv_pcache_space.action = '@control'";
            }
        });

        $app->hook('ApiQuery(Space).where', function (&$where) use($theme, $app) {
            /** @var ApiQuery $this */

            if($app->config['rcv.disableApiFilters']) {
                return;
            }

            $_where = "CAST(rcv_space_owner_meta.value AS INTEGER) = e.id";

            if($app->auth->isUserAuthenticated()) {
                if($app->user->is('admin')) {
                    $_where = "rcv_space_owner.user = {$app->user->id} OR ($_where)";
                } else {
                    $_where = "rcv_pcache_space.user = {$app->user->id} OR ($_where)";
                }
            }

            $where .= " AND ({$_where})";
        });

        $app->hook('view.requestedEntity(Registration).result', function (&$entity, $class, $id) use($app) {
            if($entity['opportunity']->id == $app->config['rcv.opportunityId']) {
                if($agent_relation = $app->repo('RegistrationAgentRelation')->findOneBy(['owner' => $id, 'group' => 'coletivo'])){
                    $entity['relatedAgents'] = (array) $entity['relatedAgents'];
                    $entity['agentRelations'] = (array) $entity['agentRelations'];

                    $entity['relatedAgents']['coletivo'] = [$agent_relation->agent];
                    $entity['agentRelations']['coletivo'] = [$agent_relation];
                }
            }
        });

        $app->hook('entity(Registration).agentRelationsAllowedStatus', function (&$status) {
            $status[] = Agent::STATUS_DRAFT;
        });

        $app->hook('entity(Registration).getAgentRelations:before', function (&$has_control, &$include_pending_relations, &$agent_statuses) use($app, $theme) {
            if($this->opportunity->id == $app->config['rcv.opportunityId']) {
                $agent_statuses[] = Agent::STATUS_DRAFT;
            }
        });

        $app->hook('controller(opportunity).render(single)', function (&$template) use($app, $theme) {
            /** @var \MapasCulturais\Controllers\Opportunity $this */

            $opportunity = $this->requestedEntity;

            if($app->config['rcv.opportunityId'] == $opportunity->id) {
                $template = 'single-cadastro';
                $theme->bodyClasses[] = 'cadastro';
            }

            if($app->config['rcv.pnabOpportunityId'] == $opportunity->id) {
                $template = 'single-pnab';
            }
        });

        $app->hook('GET(site.pncv)', function() use($app) {
            $this->render('pncv', []);
        });

        // Certificados e Selos
        $app->hook('GET(site.certificados)', function() use($app) {
            $this->render('certificados', []);
        });

        // Comissões
        $app->hook('GET(site.comissoes)', function() use($app) {
            $this->render('comissoes', []);
        });

        // Redes de Pontos e Pontões
        $app->hook('GET(site.redes-pontos-pontoes)', function() use($app) {
            $this->render('redes-pontos-pontoes', []);
        });


        // Atualização Cadastral
        $app->hook('GET(site.atualizacao-cadastral)', function() use($app) {
            $this->render('atualizacao-cadastral', []);
        });

        $app->hook('POST(site.valida-cnpj)', function() use($app, $theme) {
            $this->requireAuthentication();
            
            $fake_api = $app->config['rcv.toggleCNPJFakeApi'];

            $cpf = preg_replace('/[^\d]/', '', $app->user->profile->cpf);

            $cnpj = $fake_api ? $this->data['cnpj'] : preg_replace('/[^\d]/', '', $this->data['cnpj']);
            $valid_cnpj = $fake_api ? $theme->getCNPJFake($cnpj) : $theme->getCNPJ($cnpj, $cpf);
            
            if($valid_cnpj) {
                $app->cache->save($this->data['cnpj'], $valid_cnpj, DAY_IN_SECONDS);

                // Procurando um CNPJ nas organizações de outros usuários
                
                /** @var \MapasCulturais\Entities\AgentMeta[] */
                $array_meta = $app->repo('AgentMeta')->findBy(['key' => 'cnpj', 'value' => $this->data['cnpj']]);
                
                
                foreach($array_meta as $meta) {
                    $agent = $meta->owner;
                    if($agent->user->id !== $app->user->id) {
                        $app->disableAccessControl();
                        $nome_completo = $agent->nomeCompleto;
                        $app->enableAccessControl();
                        $this->errorJson("Este CNPJ já está cadastrado, pela organização {$nome_completo}. Para utilizá-lo, entre em contato com a organização ou com o suporte, pelo email suporte.culturaviva@cultura.gov.br");
                    }
                }
               
                // Caso receba algum erro na api da receita
                if($valid_cnpj['situacaoCadastral']['codigo'] !== '2') {
                    $invalid_cnpj = $valid_cnpj['situacaoCadastral']['motivo'];
                    $this->errorJson($invalid_cnpj);
                }

                $legal_nature = $valid_cnpj['naturezaJuridica'] ?? null;

                if($legal_nature) {
                    $legal_nature_code = $legal_nature['codigo'];
                    $allowed_legal_natures = ['1', '3', '2143', '3999', '3069', '3131', '3239', '3301', '3220'];
                }
            
                // Se a natureza jurídica não for válida
                if(!in_array($legal_nature_code, $allowed_legal_natures)) {
                    $this->errorJson('natureza-juridica-invalida');
                }

                // Se tudo der certo retorna o objeto
                $this->json($valid_cnpj);
            }

            // Caso o CNPJ for inválido
            $this->errorJson(false);
        });

        // Termo de adesão
        $app->hook('GET(site.termoAdesao)', function() use($app) {
            $this->render('termo-adesao', []);
        });
        
        // Endpoint para cadastrar organização
        $app->hook('POST(agent.register-organization)', function () {
            
            $this->requireAuthentication();

            $agent = new Agent;
            $agent->type = 2;
            $agent->name = "";
            $agent->status = Agent::STATUS_DRAFT;

            foreach ($this->data as $field => $value) {
                $agent->$field =  $value;
            }

            $agent->save(true);

            $this->json($agent);
        });

        // Carrega novos ícones 'iconfy' na estrutura default
        $app->hook('component(mc-icon).iconset', function(&$iconset){
            $iconset['graph-bar'] = "foundation:graph-bar";
            $iconset['section-share'] = "ic:baseline-ios-share";
            $iconset['section-seals'] = "ic:round-turned-in";
            $iconset['arrow-left-return'] = "la:long-arrow-alt-left";
            $iconset['arrow-right-return'] = "la:long-arrow-alt-right";
            $iconset['event'] = "bxs:calendar-event";
            $iconset['cursor-click'] = "mynaui:click-solid";
            $iconset['certificate'] = "mdi:seal-outline";
        });
        
        $app->hook('GET(site.projeto)', function() use($app) {
            $this->render('projetos', []);
        });

        $app->hook('POST(site.alterar-cnpj)', function() use($app, $theme) {
            $this->requireAuthentication();
            
            $registration_info = $this->data['registration'];
            $registration = $app->repo('Registration')->find($registration_info['id']);

            if($registration) {
                $cnpj = $this->data['cnpj'];
                $full_name = $this->data['apiInfo']['nomeEmpresarial'];

                $agent = $registration->relatedAgents['coletivo'][0];
                $conn = $app->em->getConnection();
                $cnpj_field = $conn->fetchAll("
                    SELECT 
                        *
                    FROM 
                        registration_field_configuration
                    WHERE 
                        field_type = 'agent-collective-field'
                        AND 
                            opportunity_id = {$app->config['rcv.opportunityId']}
                        AND 
                            jsonb_extract_path_text(config::jsonb, 'entityField') = 'cnpj'
                ");
                $cnpj_field_name = 'field_'.$cnpj_field[0]['id'];

                $full_name_field = $conn->fetchAll("
                    SELECT 
                        *
                    FROM 
                        registration_field_configuration
                    WHERE 
                        field_type = 'agent-collective-field'
                        AND 
                            opportunity_id = {$app->config['rcv.opportunityId']}
                        AND 
                            jsonb_extract_path_text(config::jsonb, 'entityField') = 'nomeCompleto'
                        AND EXISTS (
                            SELECT 
                                1
                            FROM 
                                jsonb_array_elements_text(categories::jsonb) AS category
                            WHERE 
                                category = '{$registration->category}'
                        );
                ");
                $full_name_field_name = 'field_'.$full_name_field[0]['id'];
                
                $app->disableAccessControl();
                $conn->exec("UPDATE registration_meta SET value = '{$cnpj}' WHERE object_id = {$registration->id} AND key = '{$cnpj_field_name}'");
                $registration->_newModifiedRevision(sprintf(i::__('campo "%s" modificado'), $cnpj_field_name));

                $conn->exec("UPDATE registration_meta SET value = '{$full_name}' WHERE object_id = {$registration->id} AND key = '{$full_name_field_name}'");
                $registration->_newModifiedRevision(sprintf(i::__('campo "%s" modificado'), $full_name_field_name));

                $evaluations = $app->repo('RegistrationEvaluation')->findBy(['registration' => $registration]);

                if($evaluations) {
                    foreach($evaluations as $evaluation) {
                        $evaluation->status = RegistrationEvaluation::STATUS_DRAFT;
                        $evaluation->save();
                    }
                }

                $registration->status = Registration::STATUS_SENT;
                $registration->range = $app->config['rcv.rangesMap']['alterar-cnpj'];
                $registration->save(true);

                $agent->cnpj = $cnpj;
                $agent->nomeCompleto = $full_name;
                $agent->save(true);
                $app->enableAccessControl();

                $this->json(true);
            }

            $this->errorJson(false);
        });

        $app->hook('entity(Registration).canUser(sendEditableFields)', function($user, &$canUser) use($app) {
            $enable_editable_fields = false;

            if(isset($this->agentsData)) {
                $agent_id = $this->agentsData['coletivo']['id'];
                $agent = $app->repo('Agent')->find($agent_id);
                $agent_relations = $agent->agentRelations;

                foreach($agent_relations as $relation) {
                    if($relation->agent->id == $user->profile->id && $relation->status == AgentRelation::STATUS_ENABLED) {
                        $enable_editable_fields = true;
                        break;
                    }
                }
            }

            if(($_SESSION["{$this}:editableFields"] ?? false) || $enable_editable_fields) {
                $canUser = true;
            }
        });

        $app->hook("entity(Registration).send:after", function () use ($app) {
            /** @var Registration $this */
            if (isset($_SESSION["{$this}:editableFields"]) && $_SESSION["{$this}:editableFields"]) {
                $this->save(true);
                unset($_SESSION["{$this}:editableFields"]);
                $this->clearPermissionCache();
            }
        });

        $app->hook('POST(site.alterar-organizacao)', function() use($app, $theme) {
            $this->requireAuthentication();
            
            $registration_info = $this->data['registration'];
            $registration = $app->repo('Registration')->find($registration_info['id']);

            $options = [
                1 => ['category' => $app->config['rcv.categoriesMap']['ponto-entidade'], 'proponentType' => 'Pessoa Jurídica'],
                2 => ['category' => $app->config['rcv.categoriesMap']['pontao'], 'proponentType' => 'Pessoa Jurídica'],
                3 => ['category' => $app->config['rcv.categoriesMap']['ponto-coletivo'], 'proponentType' => 'Coletivo'],
            ];
 
            if($registration) {
                $proponent_option = $this->data['option'];

                if($proponent_option == 1) {
                    $selected_option = $options[1];
                } else if($proponent_option == 2 || $proponent_option == 3) {
                    $selected_option = $options[2];
                } else {
                    $selected_option = $options[3];
                }
                
                $app->disableAccessControl();

                $registration_field_configuration = $registration->opportunity->registrationFieldConfigurations;
                $registration_file_configuration = $registration->opportunity->registrationFileConfigurations;
                
                $all_fields = array_merge($registration_field_configuration, $registration_file_configuration);

                $editableFields = [];
                foreach($all_fields as $field) {
                    if(in_array($registration->category, $field->categories)) {
                        $fieldName = $field->fieldName ?: $field->fileGroupName;
                        $editableFields[] = $fieldName;
                    }
                }

                $registration->editableFields = $editableFields;

                foreach($editableFields as $field) {
                    if(str_starts_with($field, 'field_')) {
                        $registration->{$field} = '';
                    } else {
                        $conn = $app->em->getConnection();
                        $files = $conn->fetchAll("
                            SELECT 
                                *
                            FROM 
                                file
                            WHERE 
                                grp = '{$field}'
                                AND 
                                object_id = {$registration->id}
                        ");

                        $file = $files ? $app->repo('File')->find($files[0]['id']) : [];

                        if($file) {
                            $file_path = $file->path;
                            if(file_exists($file_path)) {
                                unlink($file_path);
                            }
    
                            $file->delete(true);
                        }
                    }
                }

                $evaluations = $app->repo('RegistrationEvaluation')->findBy(['registration' => $registration]);

                if($evaluations) {
                    foreach($evaluations as $evaluation) {
                        $evaluation->status = RegistrationEvaluation::STATUS_DRAFT;
                        $evaluation->save();
                    }
                }

                $registration->status = Registration::STATUS_DRAFT;
                $registration->range = $app->config['rcv.rangesMap']['alterar-organizacao'];
                $registration->proponentType = $selected_option['proponentType'];
                $registration->category = $selected_option['category'];

                $registration->save();
                
                $app->enableAccessControl();

                $url = $app->createUrl('registration', 'registrationEdit', [$registration->id]);
                $this->json($url);
            }

            $this->errorJson(false);
        });

        $app->hook('panel.nav',function(&$nav_items) use($app) {
            $nav_items = [
                'panel-menu' => [
                    'label' => i::__('Menu do Painel de Controle'),
                    'column' => 'left',
                    'items' => [
                        ['route' => 'panel/index', 'icon' => 'dashboard', 'label' => i::__('Painel de Controle')],
                    ]
                ],
            
                'opportunities' => [
                    'label' => i::__(''),
                    'column' => 'left',
                    'items' => [
                        [
                            'route' => 'opportunity/registrations', 'params' => [ $app->config['rcv.opportunityId'] ], 'icon' => 'opportunity', 'label' => i::__('Gerenciar cadastros'),
                            'condition' => function () {
                                return $this->opportunity->canUser('@control');
                            },
                        ],
                        [
                            'route' => 'opportunity/allEvaluations', 'params' => [ $app->config['rcv.opportunityId'] ], 'icon' => 'opportunity', 'label' => i::__('Gerenciar avaliações'),
                            'condition' => function () {
                                return $this->opportunity->canUser('@control');
                            },
                        ],
                        [
                            'route' => 'opportunity/edit', 'params' => [ $app->config['rcv.opportunityId'] ], 'icon' => 'opportunity', 'label' => i::__('Gerenciar oportunidade'),
                            'condition' => function () {
                                return $this->opportunity->canUser('@control');
                            },
                        ],
                        [
                            'route' => 'panel/evaluations', 'icon' => 'opportunity', 'label' => i::__('Minhas avaliações'),
                            'condition' => function () use ($app) {
                                $rcv_opportunity_id = $app->config['rcv.opportunityId'];
                                $rcv_pnab_opportunity_id = $app->config['rcv.pnabOpportunityId'];
                                $opportunity = $app->repo('Opportunity')->find($rcv_opportunity_id);
                                $pnab_opportunity = $app->repo('Opportunity')->find($rcv_pnab_opportunity_id);

                                $relations = [];
                                if($opportunity->evaluationMethodConfiguration) {
                                    $_relation = $opportunity->evaluationMethodConfiguration->getUserRelation();
                                    $relations[] = $_relation;
                                }

                                if($pnab_opportunity->evaluationMethodConfiguration) {
                                    $_relation = $pnab_opportunity->evaluationMethodConfiguration->getUserRelation();
                                    $relations[] = $_relation;
                                }
                             
                                foreach($relations as $relation) {
                                    if($relation && $relation->status == EvaluationMethodConfigurationAgentRelation::STATUS_ACTIVE) {
                                        return true;
                                    }
                                }
                                return false;
                            },
                        ],
                        [
                            'route' => 'panel/registrations', 'icon' => 'opportunity', 'label' => i::__('Meus cadastros'),
                            'condition' => function () use ($app) {
                                return (($app->user->is('agent') || $app->user->getIsEvaluator()) && !$app->user->is('admin'));
                            },
                        ],
                    ],
                ],
            
                'main' => [
                    'label' => '',
                    'column' => 'left',
                    'items' => [
                        [
                            'route' => 'panel/agents', 'icon' => 'agent', 'label' => i::__('Meus Agentes'),
                            'condition' => function () use ($app) {
                                return $app->isEnabled('agents');
                            },
                        ],
                        [
                            'route' => 'panel/spaces', 'icon' => 'space', 'label' => i::__('Meus Espaços'),
                            'condition' => function () use ($app) {
                                return $app->isEnabled('spaces');
                            },
                        ],
                        [
                            'route' => 'panel/events', 'icon' => 'event', 'label' => i::__('Meus Eventos'),
                            'condition' => function () use ($app) {
                                return $app->isEnabled('events');
                            },
                        ],
                    ],
                    'condition' => function () use ($app) {
                        return $app->isEnabled('agents') || $app->isEnabled('spaces') || $app->isEnabled('events') || $app->isEnabled('projects');
                    },
                ],
            
                'more' => [
                    'label' => i::__('Outras opções'),
                    'column' => 'right',
                    'items' => [
                        ['route' => 'panel/my-account', 'icon' => 'account', 'label' => i::__('Conta e Privacidade')],
                    ]
                ],

                'admin' => [
                    'label' => i::__('Administração'),
                    'column' => 'right',
                    'condition' => function () use ($app) {
                        return $app->user->is('admin');
                    },
                    'items' => [
                        [
                            'route' => 'panel/seals',
                            'icon' => 'seal',
                            'label' => i::__('Gestão de Selos'),
                            'condition' => function () use ($app) {
                                return $app->user->is('admin');
                            }
                        ],
                        [
                            'route' => 'panel/user-management',
                            'icon' => 'user-config',
                            'label' => i::__('Gestão de usuários'),
                            'condition' => function () use ($app) {
                                return $app->user->is('admin');
                            }
                        ],
                        [
                            'route' => 'panel/system-roles',
                            'icon' => 'role',
                            'label' => i::__('Funções de usuários'),
                            'condition' => function () use ($app) {
                                return $app->user->is('saasAdmin');
                            }
                        ]
                    ]
                ],
            ];

            if ($app->user->profile) {
                $nav_items['user'] = [
                    'label' => i::__('Usuário Logado'),
                    'column' => 'user',
                    'items' => [
                        ['route' => 'agent/single', 'params' => [$app->user->profile->id], 'icon' => 'agent', 'label' => i::__('Meu Perfil')],
                        ['route' => 'auth/logout', 'icon' => 'logout', 'label' => i::__('Sair')],
                    ]
                ];
            }
        });

        $app->hook('Theme::addOpportunityBreadcramb', function($a, $label) {
            $this->breadcrumb = array_filter($this->breadcrumb ?? [], fn($crumb) => $crumb['label'] !== i::__('Período de inscrição'));
        });

        $app->hook('POST(site.atualizar-cadastro)', function() use($app, $theme) {
            $this->requireAuthentication();

            $registration_info = $this->data['registration'];
            $registration = $app->repo('Registration')->find($registration_info['id']);

            if($registration) {
                $conn = $app->em->getConnection();
                $cnpj_field = $conn->fetchAll("
                    SELECT 
                        *
                    FROM 
                        registration_field_configuration
                    WHERE 
                        field_type = 'agent-collective-field'
                        AND 
                            opportunity_id = {$app->config['rcv.opportunityId']}
                        AND 
                            jsonb_extract_path_text(config::jsonb, 'entityField') = 'cnpj'
                ");
                $cnpj_field_name = 'field_'.$cnpj_field[0]['id'];

                $full_name_field = $conn->fetchAll("
                    SELECT 
                        *
                    FROM 
                        registration_field_configuration
                    WHERE 
                        field_type = 'agent-collective-field'
                        AND 
                            opportunity_id = {$app->config['rcv.opportunityId']}
                        AND 
                            jsonb_extract_path_text(config::jsonb, 'entityField') = 'nomeCompleto'
                        AND EXISTS (
                            SELECT 
                                1
                            FROM 
                                jsonb_array_elements_text(categories::jsonb) AS category
                            WHERE 
                                category = '{$registration->category}'
                        );
                ");
                $full_name_field_name = 'field_'.$full_name_field[0]['id'];

                $full_name_owner_field = $conn->fetchAll("
                    SELECT 
                        *
                    FROM 
                        registration_field_configuration
                    WHERE 
                        field_type = 'agent-owner-field'
                        AND 
                            opportunity_id = {$app->config['rcv.opportunityId']}
                        AND 
                            jsonb_extract_path_text(config::jsonb, 'entityField') = 'nomeCompleto';
                ");
                $full_name_owner_field_name = 'field_'.$full_name_owner_field[0]['id'];

                $cpf_field = $conn->fetchAll("
                    SELECT 
                        *
                    FROM 
                        registration_field_configuration
                    WHERE 
                        field_type = 'agent-owner-field'
                        AND 
                            opportunity_id = {$app->config['rcv.opportunityId']}
                        AND 
                            jsonb_extract_path_text(config::jsonb, 'entityField') = 'cpf'
                ");
                $cpf_field_name = 'field_'.$cpf_field[0]['id'];

                $registration_field_configuration = $registration->opportunity->registrationFieldConfigurations;
                $registration_file_configuration = $registration->opportunity->registrationFileConfigurations;

                $all_fields = array_merge($registration_field_configuration, $registration_file_configuration);

                $editableFields = [];
                foreach($all_fields as $field) {
                    $fieldName = $field->fieldName ?: $field->fileGroupName;
                    $blocked_fields = [$cnpj_field_name, $full_name_field_name, $full_name_owner_field_name, $cpf_field_name];

                    if(in_array($fieldName, $blocked_fields)) {
                        continue;
                    }
                    
                    $editableFields[] = $fieldName;
                }

                $app->disableAccessControl();
                $registration->editableFields = $editableFields;
                $registration->save(true);
                $_SESSION["{$registration}:editableFields"] = true;
                $registration->clearPermissionCache();
                $app->enableAccessControl();

                $url = $app->createUrl('registration', 'registrationEdit', [$registration->id]);
                $this->json($url);
            }

            $this->errorJson(false);
        });

        $app->hook('entity(Registration).status(approved)', function() use($app, $theme) {
            /** @var Registration $this */

            // Verifica se a inscrição é da oportunidade correta
            $opportunity_id = $app->config['rcv.opportunityId'];
            if($this->opportunity->id != $opportunity_id) {
                return;
            }

            /** @var Agent */
            $coletivo = $this->relatedAgents['coletivo'][0] ?? null;

            // Verifica se existe um agente coletivo
            if (!$coletivo) {
                return;
            }

            // publica o agente coletivo
            $app->disableAccessControl();
            $coletivo->publish(true);
            $app->enableAccessControl();

            // Verifica se o coletivo tem localização pública, se tiver cria um espaço para ele
            if($coletivo->publicLocation) {
                $name = $coletivo->name;
                $full_name = $coletivo->nomeCompleto;

                if($app->user->is('admin')) {
                    $spaces_query = new ApiQuery(Space::class, ['name' => API::OR(API::ILIKE($name), API::ILIKE($full_name))]);
                    $spaces_query->addFilterByApiQuery(new ApiQuery(Agent::class, ['user' => API::EQ('@me')]), property: 'owner');
                    
                } else {
                    $spaces_query = new ApiQuery(Space::class, ['name' => API::OR(API::ILIKE($name), API::ILIKE($full_name)), '@permissions' => '@control']);
                }

                $space_ids = $spaces_query->findIds();

                $app->disableAccessControl();
                
                if($space_ids) {
                    $space = $app->repo('Space')->find($space_ids[0]);
                } else {
                    $space = new Space;
                    $space->name = $name ?: $full_name;
                }

                $space->owner = $this->relatedAgents['coletivo'][0];
                $space->location = $coletivo->location;
                $space->type = 125;
                $space->En_CEP = $coletivo->En_CEP;
                $space->En_Nome_Logradouro = $coletivo->En_Nome_Logradouro;
                $space->En_Num = $coletivo->En_Num;
                $space->En_Bairro = $coletivo->En_Bairro;
                $space->En_Municipio = $coletivo->En_Municipio;
                $space->En_Estado = $coletivo->En_Estado;
                $space->En_Complemento = $coletivo->En_Complemento ?: '';
                $space->save(true);

                $theme->createSpaceRelation($space, $this);
                $app->enableAccessControl();
            }
            
        });

        // Altera template de email ao iniciar uma inscrição
        $app->hook("sendMailNotification.registrationStart:beforeEnqueue", function(&$registration, &$template, &$enable, &$params) use ($app) {
            if($registration->opportunity->id == $app->config['rcv.opportunityId']) {
                $template = 'rcv_start_registration';
            }
        });

        $app->hook("sendMailNotification.registrationStart", function(&$registration, &$template, &$params) use ($app) {
            if($template == 'rcv_start_registration') {
                $relations = $registration->relatedAgents;
                $coletivo = $relations['coletivo'][0] ?? (object)[];
                $params['nameOrg'] = $coletivo->nomeCompleto ?? null;
                $params['cnpjOrg'] = $coletivo->cnpj ?? null;
                $params['categoryOrg'] = $registration->category;
            }
        });
        
        // Altera template de email ao envio uma inscrição
        $app->hook("sendMailNotification.registrationSend", function(&$registration, &$template, &$enable, &$params) use ($app)  {
            if($registration->opportunity->id == $app->config['rcv.opportunityId']) {
                $relations = $registration->relatedAgents;
                $coletivo = $relations['coletivo'][0] ?? (object)[];
                $params['nameOrg'] = $coletivo->nomeCompleto ?: null;
                $params['cnpjOrg'] = $coletivo->cnpj ?: null;
                $params['categoryOrg'] = $registration->category;

                if((isset($_SESSION["{$registration}:editableFields"]) && $_SESSION["{$registration}:editableFields"])) {
                    $template = 'rcv_send_registration_update' ;
                    $params['orgId'] = $coletivo->id;
                } else {
                    $template = 'rcv_send_registration';
                }

            }
        });

        // Define propriedades para auxiliar no momento de ceder a propriedade
        $app->hook('workflow(RequestChangeOwnership).approve:before', function() use($app, $theme) {
                $this->old_owner_origin_id = $this->origin->owner->id;
                $this->old_owner_destination_id = $this->destination->owner->id;
        });

        // Altera a mensagem do request para na solicitação de mudança de propriedade
        $app->hook('request(workflow.message).create:before', function($organization, $origin, $entityType, &$message_to_requester, &$send_message, $requester) use($theme) {
            if($this instanceof \MapasCulturais\Entities\RequestChangeOwnership) {
                $org_name = $organization->name;
                $org_url = $organization->singleUrl;

                $destinattion_name = $this->destination->name;
                $destinattion_url = $this->destination->singleUrl;

                $origin_url = $origin->singleUrl;

                if($organization->ownerUser->id == $this->requesterUser->id) {
                    // ceder propriedade
                    $origin_name = $organization->ownerUser->profile->name;
                    $origin_email = ($organization->ownerUser->profile->emailPrivado ??
                        $organization->ownerUser->profile->emailPublico ?? 
                        $organization->ownerUser->email);
                    $origin_phone = $organization->ownerUser->profile->telefonePublico ?? '';
                } else {
                    // reinvindicar propriedade
                    $origin_name = $origin->ownerUser->profile->name;
                    $origin_email = ($origin->ownerUser->profile->emailPrivado ??
                        $origin->ownerUser->profile->emailPublico ?? 
                        $origin->ownerUser->email);
                    $origin_phone = $origin->ownerUser->profile->telefonePublico ?? '';
                }

                $origin_link = "<a rel='noopener noreferrer' href=\"{$origin_url}\">{$origin_name}</a>";
                $org_link = "<a rel='noopener noreferrer' href=\"{$org_url}\">{$org_name}</a>";
                $destinattion_link = "<a rel='noopener noreferrer' href=\"{$destinattion_url}\">{$destinattion_name}</a>";
                $org_owner_url = "<a rel='noopener noreferrer' href=\"{$organization->owner->singleUrl}\">{$organization->owner->name}</a>";
                $subject = 'Requisição de mudança de propriedade';

                if($this->metadata['type'] === "request") {
                    $send_message = sprintf(
                        i::__("%s esta solicitando representar a organização %s.<br>E-mail de contato: %s<br>Telefone de contato: %s"),
                        $origin_link,
                        $org_link,
                        $origin_email,
                        $origin_phone
                    );
                    $subject = '[Cultura Viva] Comprovação de nova representação da organização';

                    $message_to_requester = sprintf(i::__("Sua requisição para representar a organização %s foi enviada. Aguarde a aprovação de %s."), $org_link, $org_owner_url);
                    $message_mail = "
                        Para realizarmos a alteração de propriedade da organização, precisamos que você nos envie a ata da última gestão, o estatuto da organização e um documento seu com foto.<br>
                        Além disso, precisamos que anexe uma foto sua segurando o documento com foto, para comprovarmos que você é o agente responsável por esse chamado de suporte.<br><br>

                        Aguardamos seu e-mail de retorno com esses anexos.<br><br>

                        Atenciosamente,<br>
                        Equipe de suporte<br>
                        Secretaria de Cidadania e Diversidade Cultural (SCDC)<br>
                        Ministério da Cultura";
                } else {
                    $send_message = sprintf(i::__("%s esta solicitando que você represente a organização %s"), $origin_link, $org_link);
                    $message_to_requester = sprintf(i::__("Sua solicitação para que %s represente a organização %s foi enviada. Aguarde a aprovação de %s."), $destinattion_link, $org_link, $destinattion_link);
                    $message_mail = $message_to_requester;
                }

                $theme->sendMailRequester($origin_email, $message_mail, $subject);
            }
        });

        // Altera mensagem do e-mail para adicionar os botões de rejeitar e aceitar
        $app->hook('request(workflow.message.<<destination|origin>>).sendMail', function(&$message, $notification) use($app) {
            if(get_class($this) === 'MapasCulturais\Entities\RequestChangeOwnership') {
                $approve_url = $app->createUrl('notification', 'approve', ['id' => $notification->id]);
                $reject_url = $app->createUrl('notification', 'reject', ['id' => $notification->id]);
    
                $button_css = "
                    align-items: center;
                    appearance: none;
                    border-radius: 8px;
                    cursor: pointer;
                    display: inline-flex;
                    font-size: 1rem;
                    font-weight: 600;
                    justify-content: center;
                    line-height: 1.125rem;
                    padding: 0.5625rem 1.1875rem;
                    position: relative;
                    text-decoration: none;
                ";
    
                $message = '
                    <div>
                        <p>' . $message . '</p>
                        <a href='. $reject_url . ' style="'.$button_css.'background-color: #fff;border:0.125rem solid #9B156B;color:#9B156B;">Rejeitar</a>
                        <a href='. $approve_url . ' style="'.$button_css.'background-color: #9B156B;border:0.125rem solid #9B156B;color:#fff;">Aceitar</a>
                    </div>
                ';
            }
        });

        // Altera o redirecionamento do botão de rejeitar no e-mail para single do ponto
        $app->hook('notification.reject.referer', function(&$referer) use($app) {
            /** @var \MapasCulturais\Controllers\Notification $this */
            $notification = $this->requestedEntity;
            $single_id = $notification->request->origin->id;

            $referer = $app->createUrl('agent', 'single', [$single_id]);
        });

        // Altera o redirecionamento do botão de aceitar no e-mail para single do ponto
        $app->hook('notification.approve.referer', function(&$referer) use($app) {
            /** @var \MapasCulturais\Controllers\Notification $this */
            $notification = $this->requestedEntity;
            $single_id = $notification->request->origin->id;

            $referer = $app->createUrl('agent', 'single', [$single_id]);
        });

        // Altera a mensagem do request para na aprovação da mudança de propriedade
        $app->hook('request(workflow.message).approve:before', function($organization, $origin, $entityType, &$send_message, $requester) {
            if(get_class($this) === 'MapasCulturais\Entities\RequestChangeOwnership') {
                $org_name = $organization->name;
                $org_url = $organization->singleUrl;

                $origin_url = $requester->profile->singleUrl;
                $origin_name = $requester->profile->name;

                $origin_link = "<a rel='noopener noreferrer' href=\"{$origin_url}\">{$origin_name}</a>";
                $org_link = "<a rel='noopener noreferrer' href=\"{$org_url}\">{$org_name}</a>";

                if($this->metadata['type'] === "request") {
                    $send_message = sprintf(i::__("%s aceitou sua solicitação para representar a organização %s"), $origin_link, $org_link);
                } else {
                    $send_message = sprintf(i::__("%s aceitou sua solicitação para que ele represente a organização %s"), $origin_link, $org_link);
                }
            }
        });

         // Altera a mensagem do request para na rejeição da mudança de propriedade
        $app->hook('request(workflow.message).reject:before', function($organization, $origin, $entityType, &$send_message, $requester) {
            if(get_class($this) === 'MapasCulturais\Entities\RequestChangeOwnership') {
                $org_name = $organization->name;
                $org_url = $organization->singleUrl;

                $origin_url = $requester->profile->singleUrl;
                $origin_name = $requester->profile->name;

                $origin_link = "<a rel='noopener noreferrer' href=\"{$origin_url}\">{$origin_name}</a>";
                $org_link = "<a rel='noopener noreferrer' href=\"{$org_url}\">{$org_name}</a>";

                if($this->metadata['type'] === "request") {
                    if($requester->profile->id != $origin->id) {
                        $send_message = sprintf(i::__("%s não aceitou conceder a representação da organização %s"), $origin_link, $org_link);
                    } else {
                        $send_message = sprintf(i::__("%s cancelou a solicitação para representar da organização %s"), $origin_link, $org_link);
                    }
                } else {
                    if($requester->profile->id != $origin->id) {
                        $send_message = sprintf(i::__("%s cancelou a solicitação para que você represente a organização %s"), $origin_link, $org_link);
                    } else {
                        $send_message = sprintf(i::__("%s não aceitou sua solicitação para representar a organização %s"), $origin_link, $org_link);
                    }
                }
            }
        });

        // Altera owner da inscrição ao aceitar alterar o representante da organização
        $app->hook('workflow(RequestChangeOwnership).approve:after', function() use($app, $theme) {
            if($registration = $this->origin->rcv_registration) {
                $app->disableAccessControl();

                // o destination é o novo owner da organização.
                $registration->owner = $this->destination;
                
                // atualiza o agentsData
                if($registration->status > 0) {
                    $registration->agentsData = $registration->_getAgentsData();
                } else {
                    $registration->agentsData = [];
                }

                $registration->save(true);

                $app->enqueueEntityToPCacheRecreation($registration);

                // apaga os campos @
                if($registration_field_config = $registration->opportunity->registrationFieldConfigurations) {
                    $conn = $app->em->getConnection();
                    foreach($registration_field_config as $field) {
                        if($field->fieldType === 'agent-owner-field') {
                            $field_name = "field_{$field->id}";
                            $conn->executeQuery("DELETE FROM registration_meta WHERE key = '{$field_name}' AND object_id = {$registration->id}");
                        }
                    }
                }

                $app->enableAccessControl();
            }
        });

        // Disparo de e-mail, caso solicitado pelo usuário, ao desativar um ponto/pontão
        $app->hook('POST(site.desativar-ponto)', function() use($app, $theme) {
            $this->requireAuthentication();
            
            $organization_id = $this->data['organization'];
            $organization = $app->repo('Agent')->find($organization_id);

            if($organization) {
                $agent_id = $this->data['user'];
                $agent = $app->repo('Agent')->find($agent_id);

                $message = $this->data['message'];

                $theme->sendMailNotification($app, $agent, $organization, $message);

                $this->json(true);
            }

            $this->errorJson(false);
        });

        // Após envio da avaliação que tenha faixa diferente de cadastro, altera a faixa da inscrição para cadastro e troca o avaliador para o usuário fantasma
        $app->hook('entity(RegistrationEvaluation).send:after', function() use($app, $theme) {
            /** @var RegistrationEvaluation $this */
            $registration = $this->registration;

            // Verifica se a inscrição é da oportunidade correta e se a faixa da inscrição é diferente de cadastro
            if($registration->opportunity->id == $app->config['rcv.opportunityId'] && in_array($registration->range, [$app->config['rcv.rangesMap']['alterar-cnpj'], $app->config['rcv.rangesMap']['alterar-organizacao']])) {
                $phantom_user_id = $app->config['rcv.phantomUserId'];

                $app->disableAccessControl();
                $registration->range = $app->config['rcv.rangesMap']['cadastro'];
                $registration->save(true);

                if($phantom_user = $app->repo('User')->find($phantom_user_id)) {
                    $this->user = $phantom_user;
                    $this->save(true);
                }

                $app->enableAccessControl();
            }   
        });

        $app->hook('SpreadsheetJob(entities-spreadsheets).getHeader:after', function($job, &$result) use($app, $theme) {
            if($job->entityClassName == Agent::class) {
                foreach($result as $key => $value) {
                    $result[$key] = $app->config['rcv.SpreadsheetColumnsLabels'][$key]['label'] ?? $value;
                }
            }
        });

        $app->hook('SpreadsheetJob(entities-spreadsheets).getBatch:after', function($job, &$result) use($app, $theme) {
            if($job->entityClassName == Agent::class) {
                foreach($result as &$entity) {
                    $agent = $app->repo('Agent')->find($entity['id']);

                    if($agent) {
                        if(isset($entity['tipoPonto'])) {
                            $tipo_ponto = str_replace('_', '-', $entity['tipoPonto']);
                            $entity['tipoPonto'] = $app->config['rcv.categoriesMap'][$tipo_ponto];
                        }

                        $entity['id'] = "<a href='{$agent->singleUrl}'>{$agent->singleUrl}</a>";
                        $entity['ownerName'] = $agent->owner->user->profile->name;
                        $entity['cpf'] = $agent->owner->user->profile->cpf;

                        if(array_key_exists('seals', $entity) && $agent->sealRelations && $agent->sealRelations[0]->createTimestamp) {
                            $entity['seals'] = $agent->sealRelations[0]->createTimestamp?->format('d/m/Y');
                        }

                        if (array_key_exists('rcv_sede_realizaAtividades_outros_lista', $entity) && $agent->rcv_sede_realizaAtividades_outros_lista) {
                            $addresses = json_decode($agent->rcv_sede_realizaAtividades_outros_lista, true);
                            
                            if (is_array($addresses)) {
                                $formattedAddresses = array_map(fn($data) => sprintf(
                                    "%s: %s, %s, %s, %s, %s - %s, %s",
                                    $data['nome'] ?? '',
                                    $data['logradouro'] ?? '',
                                    $data['numero'] ?? '',
                                    $data['bairro'] ?? '',
                                    $data['cidade'] ?? '',
                                    $data['complemento'] ?? '',
                                    $data['estado'] ?? '',
                                    $data['cep'] ?? ''
                                ), $addresses);
                        
                                $entity['rcv_sede_realizaAtividades_outros_lista'] = implode("\n", $formattedAddresses);
                            }
                        }
                        
                        if (in_array('rcv_links_coletivo', array_keys($entity)) && $agent->rcv_links_coletivo) {
                            $links = json_decode($agent->rcv_links_coletivo, true);
                            if (is_array($links)) { {
                                    $formatedLinks = array_map(fn($data) => sprintf(
                                        "%s: %s",
                                        $data['title'] ?? '',
                                        $data['value'] ?? '',
                                    ), $links);
                                }
                                $entity['rcv_links_coletivo'] = implode("\n", $formatedLinks);
                            }
                        }

                        if (in_array('outrosSelos', array_keys($entity))) {
                            $_result = [];
                            $verificationSeals = $app->config['rcv.verificationSeals'];
                            if ($sealRelations = $agent->sealRelations) {

                                foreach ($sealRelations as $relation) {
                                    if ($relation->seal->id != $verificationSeals['ponto'] && $relation->seal->id != $verificationSeals['pontao']) {
                                        $_result[] = $relation->seal->name;
                                    }
                                }
                            }
                            if ($_result) {
                                $entity['outrosSelos'] = implode(', ', $_result);
                            }
                        }

                        if(in_array('acao_estruturante', array_keys($entity)) && $agent->terms['acao_estruturante']) {
                           $entity['acao_estruturante'] = implode(', ', $agent->terms['acao_estruturante']);
                        }

                        if(in_array('acao_estruturante_outra', array_keys($entity)) && $agent->terms['acao_estruturante_outra']) {
                            $entity['acao_estruturante_outra'] = implode(', ', $agent->terms['acao_estruturante_outra']);
                        }

                        if(in_array('rcv_principais_segmentos', array_keys($entity)) && $agent->terms['rcv_principais_segmentos']) {
                            $entity['rcv_principais_segmentos'] = implode(', ', $agent->terms['rcv_principais_segmentos']);
                        }

                        if(in_array('rcv_atuacao_demais_segmentos', array_keys($entity)) && $agent->terms['rcv_atuacao_demais_segmentos']) {
                            $entity['rcv_atuacao_demais_segmentos'] = implode(', ', $agent->terms['rcv_atuacao_demais_segmentos']);
                        }

                        if(in_array('instancia_representacao_minc', array_keys($entity)) && $agent->terms['instancia_representacao_minc']) {
                            $entity['instancia_representacao_minc'] = implode(', ', $agent->terms['instancia_representacao_minc']);
                        }

                        if(in_array('ponto_infra_estrutura', array_keys($entity)) && $agent->terms['ponto_infra_estrutura']) {
                            $entity['ponto_infra_estrutura'] = implode(', ', $agent->terms['ponto_infra_estrutura']);
                        }

                        if(in_array('ponto_equipamentos', array_keys($entity)) && $agent->terms['ponto_equipamentos']) {
                            $entity['ponto_equipamentos'] = implode(', ', $agent->terms['ponto_equipamentos']);
                        }

                        if(in_array('ponto_recursos_humanos', array_keys($entity)) && $agent->terms['ponto_recursos_humanos']) {
                            $entity['ponto_recursos_humanos'] = implode(', ', $agent->terms['ponto_recursos_humanos']);
                        }

                        if(in_array('ponto_hospedagem', array_keys($entity)) && $agent->terms['ponto_hospedagem']) {
                            $entity['ponto_hospedagem'] = implode(', ', $agent->terms['ponto_hospedagem']);
                        }

                        if(in_array('ponto_deslocamento', array_keys($entity)) && $agent->terms['ponto_deslocamento']) {
                            $entity['ponto_deslocamento'] = implode(', ', $agent->terms['ponto_deslocamento']);
                        }

                        if(in_array('ponto_comunicacao', array_keys($entity)) && $agent->terms['ponto_comunicacao']) {
                            $entity['ponto_comunicacao'] = implode(', ', $agent->terms['ponto_comunicacao']);
                        }

                        if(in_array('ponto_sustentabilidade', array_keys($entity)) && $agent->terms['ponto_sustentabilidade']) {
                            $entity['ponto_sustentabilidade'] = implode(', ', $agent->terms['ponto_sustentabilidade']);
                        }

                        if(in_array('metodologias_areas', array_keys($entity)) && $agent->terms['metodologias_areas']) {
                            $entity['metodologias_areas'] = implode(', ', $agent->terms['metodologias_areas']);
                        }

                        if(in_array('rede_pertencente', array_keys($entity)) && $agent->terms['rede_pertencente']) {
                            $entity['rede_pertencente'] = implode(', ', $agent->terms['rede_pertencente']);
                        }
                        
                        if(in_array('area', array_keys($entity)) && $agent->terms['area']) {
                            $entity['area'] = implode(', ', $agent->terms['area']);
                        }  
                        
                         if(in_array('area_atuacao', array_keys($entity)) && $agent->terms['area_atuacao']) {
                            $entity['area_atuacao'] = implode(', ', $agent->terms['area_atuacao']);
                        }   

                        if (in_array('paisPontaPontao', array_keys($entity))) {
                            $_public = ($agent->rcv_org_brasil === "Sim") ? $agent->publicLocation : $agent->En_publicLocationPontaPontao;
                            $public = (trim(strtolower($_public)) === "sim" || is_bool($_public) && $_public === true) ? true : false;
                        
                            if ($public || $app->user->is('admin')) {
                                $entity['paisPontaPontao'] = $agent->En_Pais ?: $agent->paisPontaPontao ?: $agent->pais;
                            }
                        }

                        if (in_array('cepPontaPontao', array_keys($entity))) {
                            $_public = ($agent->rcv_org_brasil === "Sim") ? $agent->publicLocation : $agent->En_publicLocationPontaPontao;
                            $public = (trim(strtolower($_public)) === "sim" || is_bool($_public) && $_public === true) ? true : false;

                            if ($public || $app->user->is('admin')) {
                                $entity['cepPontaPontao'] = $agent->En_CEP ?: $agent->cepPontaPontao;
                            }
                        }

                        if (in_array('En_Nome_LogradouroPontaPontao', array_keys($entity))) {
                            $_public = ($agent->rcv_org_brasil === "Sim") ? $agent->publicLocation : $agent->En_publicLocationPontaPontao;
                            $public = (trim(strtolower($_public)) === "sim" || is_bool($_public) && $_public === true) ? true : false;
                        
                            if ($public || $app->user->is('admin')) {
                                $entity['En_Nome_LogradouroPontaPontao'] = $agent->En_Nome_Logradouro ?: $agent->En_Nome_LogradouroPontaPontao;
                            }
                        }

                        if (in_array('En_NumPontaPontao', array_keys($entity))) {
                            $_public = ($agent->rcv_org_brasil === "Sim") ? $agent->publicLocation : $agent->En_publicLocationPontaPontao;
                            $public = (trim(strtolower($_public)) === "sim" || is_bool($_public) && $_public === true) ? true : false;
                        
                            if ($public || $app->user->is('admin')) {
                                $entity['En_NumPontaPontao'] = $agent->En_Num ?: $agent->En_NumPontaPontao;
                            }
                        }

                        if (in_array('En_MunicipioPontaPontao', array_keys($entity))) {
                            $_public = ($agent->rcv_org_brasil === "Sim") ? $agent->publicLocation : $agent->En_publicLocationPontaPontao;
                            $public = (trim(strtolower($_public)) === "sim" || is_bool($_public) && $_public === true) ? true : false;
                        
                            if ($public || $app->user->is('admin')) {
                                $entity['En_MunicipioPontaPontao'] = $agent->En_Municipio ?: $agent->En_MunicipioPontaPontao;
                            }
                        }

                        if (in_array('En_EstadoPontaPontao', array_keys($entity))) {
                            $_public = ($agent->rcv_org_brasil === "Sim") ? $agent->publicLocation : $agent->En_publicLocationPontaPontao;
                            $public = (trim(strtolower($_public)) === "sim" || is_bool($_public) && $_public === true) ? true : false;
                        
                            if ($public || $app->user->is('admin')) {
                                $entity['En_EstadoPontaPontao'] = $agent->En_Estado ?: $agent->En_EstadoPontaPontao;
                            }
                        }
                    }
                }
            }

        });

        // Executa o registro do plugin RCV antes da execução do JOB
        $app->hook('app.executeJob:before', function() {
            $this->plugins['RCV']->register();
        });

        // Define os headers da tabela de agentes coletivos
        $app->hook('component(agent-table-2).additionalHeaders', function (&$additionalHeaders) use ($app) {
            $additionalHeaders = [];
            $skip_fields = [];
            $definitions = \MapasCulturais\Entities\Agent::getPropertiesMetadata();

            $can_see = function ($def) use ($app) {
                if ($app->user->is('admin')) {
                    return true;
                }

                if (isset($def['private']) && $def['private'] === true) {
                    return false;
                } else {
                    return true;
                }
            
            };
            
            $increment = [
                "singleUrl" => ["label" => "Url"],
                "profile" => ["label" => "Responsável"],
                "seals" => ["label" => "Certificação"],
                "ownerName" => ["label" => "Responsável"],
                "acao_estruturante" => ["label" => "Ações estruturantes da PNCV"],
                "acao_estruturante_outra" => ["label" => "Outras ações estruturantes"],
                "acao_estruturante_outra_descreva" => ["label" => "22957 - Se optou por OUTRA, descreva."],
                "rcv_principais_segmentos" => ["label" => "Principais áreas de atuação"],
                "rcv_atuacao_demais_segmentos" => ["label" => "Demais áreas de atuação"],
            ];

            $definitions = $increment + $definitions;
            
            $columns = $app->config['rcv.SpreadsheetColumnsLabels'];

            foreach($columns as $field => $params) {
                if(!in_array($field, array_keys($definitions))) {
                    continue;
                }

                $def = $definitions[$field];
                
                if (!in_array($field, $skip_fields) && in_array($field, array_keys($columns)) && !str_starts_with($field, "_") && $can_see($def)) {

                    if(!$app->user->is('admin') && !$columns[$field]['public']) {
                        continue;
                    }

                    $data = [
                        'text' => isset($columns[$field]) ? $columns[$field]['label'] : $def['label'],
                        'value' => $field,
                        'slug' => $field
                    ];

                    if(str_starts_with($field, 'geo')) {
                        $data['text'] = $def['label'] . " - Divisão geográfica";
                    }

                    if($field == "cpf") {
                        $data['value'] = 'parent?.cpf';
                    }

                    if($field == "seals") {
                        $data['value'] = "seals[0]?.createTimestamp";
                    }

                    if($field == "ownerName") {
                        $data['value'] = "parent?.name";
                    }

                    if($field == "acao_estruturante") {
                        $data['value'] = "terms['acao_estruturante'].join(', ')";
                    }

                    if($field == "acao_estruturante_outra") {
                        $data['value'] = "terms['acao_estruturante_outra'].join(', ')";
                    }

                    if($field == "rcv_principais_segmentos") {
                        $data['value'] = "terms['rcv_principais_segmentos'].join(', ')";
                    }

                    if($field == "rcv_atuacao_demais_segmentos") {
                        $data['value'] = "terms['rcv_atuacao_demais_segmentos'].join(', ')";
                    }

                    if($field == "area") {
                        $data['value'] = "terms['area']?.join(', ')";
                    }

                    if($field == "area_atuacao") {
                        $data['value'] = "terms['area_atuacao']?.join(', ')";
                    }

                    if($field == "endereco") {
                        $data['value'] = "endereco";
                    }

                    $additionalHeaders[] = $data;
                }
            }
        });

        $app->hook('component(agent-table).additionalHeaders', function (&$defaultHeaders, &$additionalHeaders, &$default_select) use ($app) {
            $defaultHeaders = [];
            $default_select = "id,seals,ownerName,En_EstadoPontaPontao,terms,parent.{id,name,cpf},singleUrl,En_CEP,En_Nome_Logradouro,En_Num,En_Complemento,En_Bairro,En_Municipio,En_Estado,En_Pais,rcv_org_brasil";
        });
       
        // Define os headers da tabela de inscrições
        $app->hook('component(opportunity-registrations-table).additionalHeaders', function (&$defaultHeaders, &$default_select, &$available_fields) use ($app) {
            $default_select = "number,consolidatedResult,agentsData,score,status,sentTimestamp,createTimestamp,updateTimestamp,files,owner.{name,geoMesoregiao},editSentTimestamp,editableUntil,editableFields";

            $organization_name_header = [
                'text' => 'Nome da organização',
                'value' => 'agentsData?.coletivo?.name',
                'slug' => 'nomeCompleto'
            ];

            $create_timestamp_header = [
                'text' => 'Última atualização',
                'value' => 'updateTimestamp',
            ];

            $agent_index = array_search('agent', array_column($defaultHeaders, 'slug'));
            $create_timestamp_index = array_search('sentTimestamp', array_column($defaultHeaders, 'value'));

            if($agent_index !== false) {
                array_splice($defaultHeaders, $agent_index + 1, 0, [$organization_name_header]);
            }
            
            if($create_timestamp_index !== false) {
                array_splice($defaultHeaders, $create_timestamp_index + 2, 0, [$create_timestamp_header]);
            }

            $available_fields = array_values( 
                                    array_filter($available_fields, function($item) {
                                        return $item['fieldName'] !== 'proponentType';
                                    })
                                );
        });

        // Atualiza a data da ultima atualização cadastral no agente
        $app->hook("entity(Registration).<<send|save>>:after", function () use ($app) {
            /** @var Registration $this */
            if (isset($_SESSION["{$this}:editableFields"]) && $_SESSION["{$this}:editableFields"]) {
                if($agentRelations = $this->agentRelations) {
                    foreach($agentRelations  as $relation) {
                        if($relation->group == "coletivo") {
                            $relation->agent->rcv_cad_updateTimestamp = $this->updateTimestamp->format('Y-m-d H:i:s');
                        }
                    }
                }
            }
        });

        // Altera nome do arquivo exportado da planilha de Agentes para Cadastro 
        $app->hook("SpreadsheetJob(entities-spreadsheets).getFilename:after", function($job, &$result) {
            if(str_starts_with($result, 'Agentes')) {
                $result = str_replace("Agentes", "Cadastro", $result);
            }
        });

        $app->hook('mustacheTemplate(export_spreadsheet.html).templateData', function(&$template_data) {
            if (str_contains($template_data->messageBody, 'Sua planilha de Agente')) {
                $template_data->messageBody = i::__('Sua planilha do Cadastro Nacional de Pontos e Pontões de Cultura foi gerada e está pronta para ser baixada. Acesse o link abaixo para obter o arquivo:');
            }
        });

        $app->hook('POST(site.enviar-duvida)', function() use($app, $theme) {
            $this->requireAuthentication();
            
            $name = $this->data['name'];
            $email = $this->data['email'];
            $question = $this->data['question'];

            if($name && $email && $question) {
                $theme->sendMailQuestion($app, $name, $email, $question);

                $this->json(true);
            }

            $this->errorJson(false);
        });

        $app->hook('entity(Registration).statusesNames', function(&$statuses) use($app){
            $opportunity = $app->view->controller->requestedEntity;

            if($opportunity->id == $app->config['rcv.opportunityId']){
                $status = [
                    10 => "Habilitado", 
                    3 => "Inabilitado",
                ];
    
                foreach ($status as $key => $value) {
                    if (isset($statuses[$key])) {
                        $statuses[$key] = $value;
                    }
                }
    
                unset($statuses[8], $statuses[2]);
            }
        });

        // Valida a planilha das organizações certificadas antes do envio da inscrição
        $app->hook('entity(Registration).sendValidationErrors', function(&$errorsResult) use ($app, $self) {
            /** @var \MapasCulturais\Entities\Registration $this */

            if ($this->opportunity->id !== (int) $app->config['rcv.pnabOpportunityId']) {
                return;
            }

            $field_file_id = 'file_' . $app->config['rcv.pnabOpportunityAttachmentId'];
            $pnab_attachment_id = 'rfc_' . $app->config['rcv.pnabOpportunityAttachmentId'];

            if (!isset($this->files[$pnab_attachment_id])) {
                return;
            }

            if ($sheet = Importer::getSheet($this->files[$pnab_attachment_id])) {
                $header = $sheet->rangeToArray("A1:" . $sheet->getHighestColumn() . "1", null, true, true, true)[1];
                $data_range = $sheet->rangeToArray("A2:" . $sheet->getHighestColumn() . $sheet->getHighestRow(), null, true, true, true);

                if (count($data_range) === 0) {
                    $errorsResult[$field_file_id] = [i::__('A planilha deve conter pelo menos uma linha de dados.')];
                    return;
                }

                $validate_rows = [];

                foreach ($data_range as $index => $row) {
                    if (!array_filter($row)) {
                        continue;
                    }

                    $parsed_row = Importer::parseRow($header, $row);

                    if ($validate_row = Importer::validateRow($parsed_row, $index)) {
                        $validate_rows = array_merge($validate_rows, $validate_row);
                    }
                }

                if (!empty($validate_rows)) {
                    $errorsResult[$field_file_id] = $validate_rows;
                }
            }
        });

        $app->hook('template(registration.view.main-app):before', function() use($app){
            $registration = $this->controller->requestedEntity;
            $field_name =  $app->config['rcv.fieldQuestion'];

            if (empty($field_name)) {
                return;
            }

            if ($registration->opportunity->id == $app->config['rcv.opportunityId'] && $registration->$field_name == $app->config['rcv.questionResponse']) {
                $app->view->enqueueScript('components', 'registrationView', 'js/registration-view.js', ['opportunity-phases-timeline']);
            }
        });

        // Remove pergunta "A organização está concorrendo em algum edital da Cultura Viva atualmente" da tela de atualização cadastral
        $app->hook('entity(Opportunity).registrationFieldConfigurations', function(&$result) use ($app, $self) {
            /** @var \MapasCulturais\Entities\Opportunity $this */

            $controller = $app->view->controller;

            if($this->id == $app->config['rcv.opportunityId'] && $controller && $controller->action == 'registrationEdit') {
                $concorrendo_edital = $app->config['rcv.concorrendoEditalField'];
                
                $result = array_filter($result, function($field) use ($concorrendo_edital) {
                    return $field->fieldName != $concorrendo_edital;
                });

                $result = array_values($result);
            }
        });

        // Altera nome do arquivo exportado da planilha de Inscrições para lista-gestores 
        $app->hook("SpreadsheetJob(registrations-spreadsheets).getFilename:after", function($job, &$result) use ($app, $self) {
            $opportunity = $job->owner;
            
            if($opportunity->id == $app->config['rcv.opportunityId']) {
                $extension = $job->extension;
                $date = date('Y-m-d H:i:s');
                
                $result = "lista-gestores-{$opportunity->id}--{$date}.{$extension}";
            }
        });

        $app->hook('component(opportunity-phases-timeline).item:after', function () use ($app) {
            $controller = $app->view->controller;
            $certificate = null;

            if ($controller->id === 'registration') {
                /** @var Registration */
                $registration = $controller->requestedEntity;
                /** @var Agent|null */
                $coletivo = $registration->relatedAgents['coletivo'][0] ?? null;
                if ($coletivo) {
                    foreach ($coletivo->sealRelations as $seal_relation) {
                        $seal_id = $seal_relation->seal->id;
                        if ($seal_id == $app->config['rcv.verificationSeals']['ponto'] || $seal_id == $app->config['rcv.verificationSeals']['pontao']) {
                            $certificate = $seal_relation;
                            break;
                        }
                    }
                }
            }

            if ($certificate) {
            ?>
                <div class="rcv-certificate-link">
                    <a class="button button--primary button--icon" href="<?= $certificate->singleUrl ?>">
                        <mc-icon name="print"></mc-icon> Imprimir certificado
                    </a>
                </div>
            <?php
            }
        });

        // Altera textos da tela de edição da inscrição para a oportunidade do pnab
        $app->hook('view.partial(registration/edit):before', function () use ($app) {
            $registration = $this->controller->requestedEntity;
            $opportunity = $registration->opportunity;

            if($opportunity->id == $app->config['rcv.pnabOpportunityId']) {
                $app->config['text:registration-autosave-notification.registration_alert_message'] = 'Os dados serão salvos automaticamente a cada {{resultTime}} segundos.';
                $app->config['text:registration.view.rcv-registration-info.registration_title'] = 'Informações';
                $app->config['text:registration.view.registration-actions.registration_actions_alert_content'] = 'Só é possível enviar após o preenchimento de todos os campos obrigatórios';
            }
        });

        Importer::init($self);
    }

    function register() {
        $app = App::i();

        parent::register();

        $this->registerRegistrationMetadata('rcv_tipo', [
            'label' => 'Tipo do agente',
            'type' => 'string',
        ]);
        
        $this->registerRegistrationMetadata('rcv_locked_fields', [
            'label' => 'Campos bloqueados',
            'type' => 'array',
            'readonly' => true
        ]);
    }

    function getCNPJFake($cnpj) {
        $app = App::i();

        $cnpjData = $app->config['rcv.CNPJsFakes'];

        return $cnpjData[$cnpj] ?? false;
    }

    public function getCNPJ($cnpj, $cpf = null, $source = 'modal') {
        $token = $this->getBscToken();

        if(!$token['success']) {
            $this->generateLog($cnpj, $token['error'], $source);
            return;
        }

        $data = json_encode(
            array(
                "cacheEvict" => false,
                "cnpj" => "$cnpj",
                "cpfConsulta" => "$cpf",
                "ipOrigem" => isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : "127.0.0.1",
                "ipUsuario" => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "127.0.0.1",
                "usuario" => "admin.user"
            )
        );

        $url = env('RCV_BSC_VALIDATE_CNPJ', '');

        $ch = curl_init();
    
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            "Authorization: Bearer {$token['accessToken']}",
            "Content-Type: application/json"
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        
        $result = curl_exec($ch);
        $error = curl_error($ch);

        curl_close($ch);

        $response = json_decode($result, true);

        $log_response = !$response  ? 'CNPJ invalido' : $response;

        if($error) {
            $log_response = $error;
        }
        
        $this->generateLog($cnpj, $log_response, $source);
        
        return $response['responseBody'] ?? null;
    }

    function getBscToken() {
        $request = curl_init();
        $client_id = env('RCV_BSC_CLIENT_ID', '');
        $client_secret = env('RCV_BSC_CLIENT_SECRET', '');
        $url = env('RCV_BSC_AUTH_TOKEN', '');

        curl_setopt_array($request, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => "GET",
            CURLOPT_HTTPHEADER => [
              "Content-type: application/json",
              "clientId: {$client_id}",
              "clientSecret: {$client_secret}",
            ],
        ]);
        
        $result = curl_exec($request);
        $response = json_decode($result, true);
        $error = curl_error($request);
        curl_close($request);

        if($error) {
            return ['success' => false, 'error' => $error];
        }
        
        return ['success' => true, 'accessToken' => $response['accessToken']];
    }

    function canUserControlRCV() {
        return $this->opportunity->canUser('@control');
    }

    function createSpaceRelation(Space $space, Registration $registration): RegistrationSpaceRelation {
        $relation = new RegistrationSpaceRelation;
        $relation->space = $space;
        $relation->owner = $registration;
        $relation->save(true);


        $collective_agent = $registration->relatedAgents['coletivo'][0];
        $collective_agent->rcv_sede_spaceId = $space->id;
        $collective_agent->save(true);

        return $relation;
    }

    function sendMailNotification($app, Agent $agent, Agent $organization, $message) {
        $filename = $app->view->resolveFilename("views/emails", "disable_cultural_hub.html");
        $template = file_get_contents($filename);

        $params = [
            "siteName" => $app->siteName,
            "baseUrl" => $app->getBaseUrl(),
            'messageBody' => $message,
            'userName' => $agent->name,
            'organization' => $organization->name ?: $organization->nomeCompleto,
        ];
        
        $mustache = new \Mustache_Engine();
        $content = $mustache->render($template, $params);

        $app->createAndSendMailMessage([
            'from' => $agent->emailPrivado,
            'to' => $app->config['rcv.email'],
            'subject' => "[{$app->siteName}] Desativar ponto/pontão de cultura",
            'body' => $content,
        ]);
    }

    function sendMailQuestion($app, $name, $email, $message) {
        $filename = $app->view->resolveFilename("views/emails", "send_question.html");
        $template = file_get_contents($filename);

        $params = [
            "siteName" => $app->siteName,
            "baseUrl" => $app->getBaseUrl(),
            'messageBody' => $message,
            'userName' => $name,
            'userEmail' => $email
        ];
        
        $mustache = new \Mustache_Engine();
        $content = $mustache->render($template, $params);

        $app->createAndSendMailMessage([
            'from' => $app->config['mailer.from'],
            'to' => $app->config['rcv.email'],
            'replyTo' => $email,
            'subject' => "[{$app->siteName}] Dúvida sobre atualização cadastral",
            'body' => $content,
        ]);
    }

    public function sendMailRequester($to, $msg, $subject = null) {
        $app = App::i();
        $dataValue = [
            'message'    => $msg
        ];
        $message = $app->renderMailerTemplate('request_relation', $dataValue);
        $subject = $subject == null ? $message['title'] : $subject;
        $mail = [
            'from'    => $app->config['mailer.from'],
            'to'      => $to,
            'subject' => $subject,
            'body'    => $message['body']
        ];
        $app->sendMailMessage($app->createMailMessage($mail));
    }

    public function generateLog($cnpj, $response, $source) {
        $app = App::i();
        
        $user = $app->user;
        $timestamp = date('Y-m-d H:i:s');
        $api_response = json_encode($response);

        $log = "---------------------------\n";
        $log .= "Usuário: {$user}\n";
        $log .= "CNPJ: {$cnpj}\n";
        $log .= "Origem: {$source}\n";
        $log .= "Horário: {$timestamp}\n";
        $log .= "Resposta da API:\n{$api_response}\n";
        $log .= "---------------------------\n\n";

        $log_path = PRIVATE_FILES_PATH . 'cnpj_validation_log.txt';
        file_put_contents($log_path, $log, FILE_APPEND);
    }
}