/*
Você atuará como especialista para implementar novos métodos e fazer correções.

Contexto técnico:
    a) Ambiente: PHP 7.4
    b) Framework: MadBuilder (Fork do Adianti Framework)
    c) Banco de dados: MySQL
    d) Sistema tem  estrutura de matriz e múltiplas filiais

Diretrizes obrigatórias:
    Restrição crítica:
        Não há acesso ao servidor
        A refatoração é permitida exclusivamente dentro do bloco refatoravel:
            //Inicio do bloco que pode refatorar ---------------------------------------------------------------------

            //Fim do bloco que pode refatorar ------------------------------------------------------------------------

    Resposta:
        Direta
        Técnica
        Sem introduções
        Sem explicações longas
        Sem tutoriais
        Sem pseudocódigo
        Sem trechos incompletos

    Proibido alterar:
        Nomes de variáveis
        Métodos
        Classes
        Campos
        IDs
        Eventos
        Fluxo principal existente
        Mantenha integralmente a arquitetura existente para manter a compatibilidade do projeto existente.

    Entrega:
        Gerar exclusivamente o método que foi solicitado e sempre completo pronto para ser substituido para evitar erros
        Sempre destacar dentro do metodo onde a correção foi iniciada e finalizada e colocar a data e hora e explicar a correção feita
        Antes de retirar algum trecho de codigo original deve explicar o motivo e se eu confirmar dai tudo bem pode fazer a retirada

    Debug:
        Se for solicitado para gerar DEBUG usar TScript::create("console.log('=== DEBUG onOpenCalendarForm FINALIZADO ===');");
        O debug deve ser iniciado na primeira linha do metodo ate a ultima linha afim de pegar todo o processo e colocar a seguinte observação exemplo debug-onsave 01 /  debug-onsave 02 a medida que for incluindo ir colocando a sequencia
        Não altere nada do codigo oiginal simplismente coloque o debug para encontrar o erro.
        So pode retirar o debug depois que for solicitado por escrito

    Prioridade:
        Soluções compatíveis e sem necessidade de acesso ao servidor

    Contexto insuficiente:
        Perguntar antes

    Objetivo:
        Corrigir
        Implementar
        Preservar a compatibilidade total com as regras existentes

    Fonte principal:
        Sempre analisar integralmente o arquivo enviado

    Instrução final:
        Analise o arquivo enviado
        Não forneça nenhuma solução fora das regras citadas acima.
        Gerar o arquiovo md completo para caso tenha algum problema possa ler e executar tudo sem ter que iniciar o processo novamente.
        Se perceber que a solução proposta não esta funcionando, sugira colocar um debug na terceira tentativa.

    Tarefa:

//--------------------------------------------------------------------------------------------------------


Usa BootstrapFormBuilder, TDataGrid, TPageNavigation, com appendPage(), addFields() com layout em array
Métodos: onShow (para abrir form), onEdit, onSave, onDelete, onSearch, onReload
Banco definido em variável estática private static $database = 'bdgestorweb', self::$database, self::$activeRecord
Form: modal com parent::setSize(0.60, null)
Form extende TWindow (não TStandardForm)
List extende TPage (não TStandardList)
Datagrid usa BootstrapDatagridWrapper com disableDefaultClick()
Actions usam setUseButton(false) e setButtonClass()
Usa TBreadCrumb::create() em vez de TXMLBreadCrumb

//--------------------------------------------------------------------------------------------------------
Resumo da compreensão:

Papel: Especialista em implementação/correção de código PHP 7.4 no MadBuilder (fork Adianti)
Restrições críticas:

Refatorar APENAS entre blocos comentados específicos
Sem acesso ao servidor
Nenhuma alteração em nomes, métodos, classes, variáveis, IDs, eventos
Manter fluxo principal intacto


Entrega obrigatória:

Código completo e pronto para substituição imediata
Sem pseudocódigo, tutoriais ou explicações longas
Resposta direta e técnica


Debug:

Console.log ou TMessage apenas
Do início ao fim do método
Remover apenas com autorização explícita


Processo:

Analisar integralmente o arquivo ANTES de propor mudanças
Perguntar se contexto for insuficiente
Preservar 100% compatibilidade com sistema existente
//--------------------------------------------------------------------------------------------------------
Você atuará como especialista para implementar novos metodos e corrigir metodos existentes em

Contexto técnico:
    a)Ambiente PHP 7.4.
    b)Framework Madbuilder é um Fork do Adianti Framework.
    c)Bando de dados MYSQL
    d)Sistema desenvolvido utiliza recurso de matriz e varias filiais
    E)Você atuará como especialista para implementar e fazer correções

Diretrizes para resposta:
    1)Restrição crítica: Não tenho acesso ao servidor para realizar procedimentos, as modificações devem ser feitas exclusivamente nos blocos comentados onde esta escrito 
             //Inicio do bloco que pode refatorar ---------------------------------------------------------------------
            
             //Fim do bloco que pode refatorar ------------------------------------------------------------------------
    2)Objetividade: Resposta direta e sem introduções ou explicações, a menos que eu solicite e não incluir Explicações longas,Introduções,Tutoriais,Comentários desnecessários,Trechos incompletos,Pseudocódigo
    3)Fidelidade ao código: Proibido alterar nomenclaturas de variáveis, métodos ou classes originais.
    4)Entrega completa: gere exclusivamente o método completo corrigido ou novo método solicitado, pronto para substituição imediata, sem alterar nomenclaturas existentes.
    5)Debug: Se for solicitado debug , você deve fazer via console.log do navegador ou usando o TMessage do framework e ou atraves de var_dump.
    6)Priorize soluções que não exijam acesso ao servidor
    7)Evite suposições, se faltar contexto, pergunte antes de fazer qualquer modificação.
    8)Objetivo e refatorar e corrigir mantendo sempre a compatibilidade total com o código existente.
    9)Leia o arquivo enviado nele ja contem todas as informações sobre a tarefa.

Tarefa:
Refatore o código abaixo seguindo as Diretrizes para resposta.
//--------------------------------------------------------------------------------------------------------
E me forneca a solução dentro do que foi estabelecido nas regras


Dica de mestre: Se a IA começar a "alucinar" nomes de classes que não existem no Adianti, responda apenas: "Você violou a regra 2. Releia as nomenclaturas originais e corrija." Ela costuma entrar na linha na hora.
//-------------------------------------------------------------------

1)PRECISO QUE SEJA OBJETIVO EM SUA RESPOSTA, NAO FIQUE CRIANDO OU ALTERANDO NOMEMCLATURAS DO CODIGO ORIGINAL SEM PERGUNTAR ANTES
2)UTILIZO MADBUILDER PHP FORK DO ADIANTI FRAMEWORK 7.4
3)NAO TENHO ACESSO AO SERVIDOR PARA REALIZAR PROCEDIMENTOS
4)GERAÇÃO DE LOG PELO CONSOLE DO NAVEGADOR OU USANDO ALGUM RECURSO VISUAL
5)FAÇA BACKUP DO CÓDIGO ORIGINAL
6)APRESENTE A CORREÇÃO OU MELHORIA DO METODO POR COMPLETO PARA EVITAR ERROS
7)SO PODE FAZER MODIFICAÇÃO NO FRAMEWORK ONDE ESTA ESCRITO //Aqui pode incluir---------------------------------------------------------------------
REFATORAR

2. Técnica do "Readonly" Temporário (JavaScript)
Esta é a técnica mais robusta atualmente. O navegador não aplica autocomplete em campos marcados como readonly. Podemos desabilitar o readonly assim que o usuário clica no campo.

Você pode adicionar isso no onShow() da sua página ou em um arquivo JS global do sistema:

Projeto:
Criar projeto chamado SimuladorDePreco que atenda a precificação de produtos ou serviços.
Cadastrar em tabela os registros que foram gerados pela simulação, e com isso acompanhar a evolução destas simulação.
Incluir despesas sendo elas federal, estadual e municipal e tambem local como agua, luz, entre outros gastos e tudo deve ser calculado penso que a melhor forma seja em porcentagem.
Cadastrar varios produtos ou serviço para a empresa ou filial que for utilizar separadamente.
Como utiliza o conceito de empresa e filias pode ter diferença nos precos praticados entre elas.
Fazer pesquisa na internet com a fonte , data e hora e site ou o meio utilizado para encontrar os preços praticados na regiao onde a empresa esta situada e caso nao encontre procurar em cidades proximas para poder o usuario avaliar se o preço esta ou nao muito maior que o concorrente.
Sugerir melhorias para calcular o preco de venda ou servico utilizando melhores praticas do mercado e ate mesmo utilização de metodoliga cientifica
Sugerir melhorias e seguir as boas praticas de mercado para o desenvolvimento deste projeto.
Criar as tabelas, codigos e tudo mais para ser implementados no sistema.
Prefixo das tabelas deve ser simuladordepreco_xxx e por ai vai
sk-3aeee3f5ceb342b99b25245fa3573db8

https://www.scrapy.org/download
https://langsearch.com
https://www.search1api.com/
https://typesense.org/

*/
/*
    public static function bkp_onOpenCalendarForm($param)
    {
        try
        {
        $slotId = $param['id'] ?? '';

        // Verifica se outro slot já foi processado neste clique
        $ultimoSlot = TSession::getValue('ultimo_slot_processado');
        $tempoUltimoSlot = TSession::getValue('ultimo_slot_tempo');
        $agora = microtime(true);

        // Se o mesmo slot ou outro slot foi processado há menos de 3 segundos, bloqueia
        if ($ultimoSlot && ($agora - $tempoUltimoSlot) < 3) {
            return;
        }

        // Registra este slot como processado
        TSession::setValue('ultimo_slot_processado', $slotId);
        TSession::setValue('ultimo_slot_tempo', $agora);

            if (TSession::getValue('agendamento_em_processamento') === true)
            {
                return;
            }

            // Marca que estamos processando agendamento
            TSession::setValue('agendamento_em_processamento', true);
            $slotRowId = 'row_' . ($param['id'] ?? '');

            // CORREÇÃO: Substituído MutationObserver problemático por setTimeout seguro
            if (!empty($slotRowId) && strpos($slotRowId, 'row_SLOT_') !== false)
            {
                // debug-onOpenCalendarForm 07

                TScript::create("
                    (function() {
                        var slotRowId = '" . addslashes($slotRowId) . "';
                        setTimeout(function() 
                        {
                            var slot = document.getElementById(slotRowId);
                            if (slot && slot.parentNode) 
                            {
                                slot.parentNode.removeChild(slot);
                            } 
                            else 
                            {

                            }
                        }, 2000);
                    })();
                ");
            }

            $horario_inicial  = $param['horario_inicial']  ?? null;
            $horario_final    = $param['horario_final']    ?? null;
            $profissional_id  = $param['profissional_id']  ?? null;
            $ambiente_id      = $param['ambiente_id']      ?? null;
            $empresa_id       = $param['empresa_id']       ?? TSession::getValue('userunitid');
            $paciente_id      = $param['paciente_id']      ?? null;

            if (!$horario_inicial || !$profissional_id)
            {
                TSession::setValue('agendamento_em_processamento', false);
                new TMessage('error', 'Parametros insuficientes para abrir o agendamento.');
                return;
            }

            TTransaction::open(self::$database);

            // VERIFICACAO DE MULTIPLOS PACIENTES NO HORARIO
            $pacientes_list  = self::buscarPacientesHorario($horario_inicial, $profissional_id);
            $total_pacientes = count($pacientes_list);

            // Se houver multiplos pacientes, busca o paciente que se encaixa HOJE
                if ($total_pacientes > 1 && empty($paciente_id))
                {
                    // Extrair a data e horários para comparação e exibição
                    $data_selecionada           = null;
                    $data_selecionada_formatada = '';
                    $horario_inicial_formatado  = '';
                    $horario_final_formatado    = '';
                    try
                    {
                        $dtTemp = new DateTime($horario_inicial);
                        $data_selecionada           = $dtTemp->format('Y-m-d');
                        $data_selecionada_formatada = $dtTemp->format('d/m/Y');
                        $horario_inicial_formatado  = $dtTemp->format('H:i');

                        if (!empty($horario_final))
                        {
                            $dtFim = new DateTime($horario_final);
                            $horario_final_formatado = $dtFim->format('H:i');
                        }
                    }
                    catch (Exception $e) {}

                    // Monta as informações de todos os pacientes com seus dados
                    $pacientes_info               = [];
                    $paciente_com_proximo_vencido = null;

                    foreach ($pacientes_list as $pac_id => $pac_nome)
                    {
                        try
                        {
                            $paciente = Pessoa::find($pac_id);
                            if (!$paciente)
                            {
                                continue;
                            }

                            $dias_frequencia        = 'N/A';
                            $dias_frequencia_person = null;

                            if (!empty($paciente->sessoes_frequenciaemdias))
                            {
                                $dias_frequencia_person = (int)$paciente->sessoes_frequenciaemdias;
                                if ($dias_frequencia_person && $dias_frequencia_person > 0)
                                {
                                    $dias_frequencia = $dias_frequencia_person;
                                }
                            }

                            $ultimo_agendamento = Agendamento::where('paciente_id', '=', $pac_id)
                                ->where('profissional_id', '=', $profissional_id)
                                ->where('status',         '!=', '04')
                                ->orderBy('horario_inicial', 'desc')
                                ->first();

                            $ultimo_agende_data  = 'N/A';
                            $proximo_agende_data = 'N/A';
                            $vencido             = false;

                            if ($ultimo_agendamento)
                            {
                                try
                                {
                                    $dt_ultimo          = new DateTime($ultimo_agendamento->horario_inicial);
                                    $ultimo_agende_data = $dt_ultimo->format('d/m/Y');
                                }
                                catch (Exception $e) {}

                                if ($dias_frequencia_person && $dias_frequencia_person > 0)
                                {
                                    try
                                    {
                                        $dt_proximo          = new DateTime($ultimo_agendamento->horario_inicial);
                                        $dt_proximo->modify('+' . $dias_frequencia_person . ' days');
                                        $proximo_agende_data = $dt_proximo->format('d/m/Y');

                                        if ($data_selecionada && $dt_proximo->format('Y-m-d') == $data_selecionada)
                                        {
                                            $vencido = true;
                                            if (!$paciente_com_proximo_vencido)
                                            {
                                                $paciente_com_proximo_vencido = 
                                                [
                                                    'paciente_id'         => $pac_id,
                                                    'nome_paciente'       => $pac_nome,
                                                    'ultimo_agendamento'  => $ultimo_agende_data,
                                                    'proximo_agendamento' => $proximo_agende_data,
                                                    'frequencia_dias'     => $dias_frequencia
                                                ];
                                            }
                                        }
                                    }
                                    catch (Exception $e) {}
                                }
                            }

                            $pacientes_info[] = [
                                'paciente_id'         => $pac_id,
                                'nome'                => $pac_nome,
                                'ultimo_agendamento'  => $ultimo_agende_data,
                                'proximo_agendamento' => $proximo_agende_data,
                                'frequencia_dias'     => $dias_frequencia,
                                'vencido'             => $vencido
                            ];
                        }
                        catch (Exception $e)
                        {
                            $pacientes_info[] = 
                            [
                                'paciente_id'         => $pac_id,
                                'nome'                => $pac_nome,
                                'ultimo_agendamento'  => 'N/A',
                                'proximo_agendamento' => 'N/A',
                                'frequencia_dias'     => 'N/A',
                                'vencido'             => false
                            ];
                        }
                    }

                    $msg_multiplos  = "<div style='font-size: 11px; margin-left: 0px;'>";
                    $msg_multiplos .= "<b style='color: #D32F2F;'>DATA SELECIONADA: {$data_selecionada_formatada}</b>";

                    if (!empty($horario_inicial_formatado))
                    {
                        $msg_multiplos .= " <b style='color: #D32F2F;'>das {$horario_inicial_formatado}";
                        if (!empty($horario_final_formatado))
                        {
                            $msg_multiplos .= " às {$horario_final_formatado}";
                        }
                        $msg_multiplos .= "</b>";
                    }

                    $msg_multiplos .= "<br>";
                    $msg_multiplos .= "<br>";
                    $msg_multiplos .= "<br>";
                    $msg_multiplos .= "<div style='background: #FFEBEE; padding: 0px; border-radius: 0px; margin: 2px 0 2px -50px; border-left: 4px solid #D32F2F;'>";
                    $msg_multiplos .= "<div style='color: #000000; font-size: 11px; padding: 2px 4px 2px 8px;'>";
                    $msg_multiplos .= "<b>ESTE HORÁRIO POSSÍ {$total_pacientes} PACIENTES</b><br>";
                    $msg_multiplos .= "</div>";

                    foreach ($pacientes_info as $info)
                    {
                        $cor_frequencia   = '#1976D2';
                        $texto_frequencia = 'Sem informação';

                        if ($info['frequencia_dias'] != 'N/A' && is_numeric($info['frequencia_dias']))
                        {
                            $dias = (int)$info['frequencia_dias'];
                            if ($dias <= 7)
                            {
                                $texto_frequencia = "A cada {$dias} dias (Semanal)";
                                $cor_frequencia   = '#D32F2F';
                            }
                            elseif ($dias <= 14)
                            {
                                $texto_frequencia = "A cada {$dias} dias (Quinzenal)";
                                $cor_frequencia   = '#FF9800';
                            }
                            elseif ($dias <= 30)
                            {
                                $texto_frequencia = "A cada {$dias} dias (Mensal)";
                                $cor_frequencia   = '#1976D2';
                            }
                            else
                            {
                                $texto_frequencia = "A cada {$dias} dias";
                                $cor_frequencia   = '#666';
                            }
                        }
                        else
                        {
                            $texto_frequencia = "Sem frequência cadastrada";
                            $cor_frequencia   = '#FF5722';
                        }

                        $msg_multiplos .= "<div style='margin: 0px 0 0px -50px; padding: 2px 4px 2px 54px; background: rgba(255,255,255,0.3); border-radius: 0px; border-left: 3px solid {$cor_frequencia}; font-size: 11px; color: #000000;'>";
                        $msg_multiplos .= "<b>ID: {$info['paciente_id']} - {$info['nome']}</b><br>";
                        $msg_multiplos .= "-> Último atendimento: {$info['ultimo_agendamento']} Próximo: {$info['proximo_agendamento']} <br>";
                        $msg_multiplos .= "-> Frequência: {$texto_frequencia}";
                        $msg_multiplos .= "</div>";
                    }

                    $msg_multiplos .= "</div>";
                    $msg_multiplos .= "<br>";

                    if ($paciente_com_proximo_vencido)
                    {
                        $msg_multiplos .= "<b style='color: #1976D2; font-size: 11px;'>RECOMENDAÇÃO DO SISTEMA:</b><br>";
                        $msg_multiplos .= "<div style='background: #E3F2FD; padding: 0px; border-radius: 0px; margin: 2px 0 2px -50px; border-left: 4px solid #1976D2;'>";
                        $msg_multiplos .= "<span style='font-size: 11px; padding: 2px 4px 2px 54px; display: block;'><b>Paciente Sugerido:</b> ID {$paciente_com_proximo_vencido['paciente_id']} - {$paciente_com_proximo_vencido['nome_paciente']}</span>";
                        $msg_multiplos .= "<span style='font-size: 11px; padding: 2px 4px 2px 54px; display: block;'><b>Última Sessão:</b> {$paciente_com_proximo_vencido['ultimo_agendamento']}</span>";

                        $freq_text = 'Sem informação';
                        if (!empty($paciente_com_proximo_vencido['frequencia_dias']) && is_numeric($paciente_com_proximo_vencido['frequencia_dias']))
                        {
                            $freq_text = $paciente_com_proximo_vencido['frequencia_dias'] . ' dias';
                        }
                        $msg_multiplos .= "<span style='font-size: 11px; padding: 2px 4px 2px 54px; display: block;'><b>Frequência:</b> {$freq_text}</span>";
                        $msg_multiplos .= "<span style='font-size: 11px; padding: 2px 4px 2px 54px; display: block;'><b>Próximo:</b> {$paciente_com_proximo_vencido['proximo_agendamento']} <span style='color: #D32F2F;'>VENCIDO</span></span>";
                        $msg_multiplos .= "</div>";
                        $msg_multiplos .= "<br>";

                        $paciente_id    = $paciente_com_proximo_vencido['paciente_id'];
                        $msg_multiplos .= "<b>Deseja agendar este paciente?</b>";

                        $action_sim = new TAction([__CLASS__, 'onConfirmMultiplePacientes'], 
                        [
                            'paciente_id'      => $paciente_id,
                            'horario_inicial'  => $horario_inicial,
                            'horario_final'    => $horario_final,
                            'profissional_id'  => $profissional_id,
                            'ambiente_id'      => $ambiente_id,
                            'empresa_id'       => $empresa_id
                        ]);
                    }
                    else
                    {
                        $msg_multiplos .= "<div style='background: #FFF3E0; padding: 0px; border-radius: 0px; margin: 2px 0 2px -50px; border-left: 4px solid #FF9800;'>";
                        $msg_multiplos .= "<b style='color: #FF9800; font-size: 11px; padding: 2px 4px 2px 54px; display: block;'>NENHUM PACIENTE COM AGENDAMENTO PARA ESTA DATA</b>";
                        $msg_multiplos .= "</div>";
                        $msg_multiplos .= "<br>";
                        $msg_multiplos .= "<b style='color: black; font-size: 11px; padding: 2px 4px 2px 54px; display: block;'>INICIAR UM AGENDAMENTO CLIQUE EM SIM?</b>";

                        $action_sim = new TAction([__CLASS__, 'onConfirmMultiplePacientes'], 
                        [
                            'paciente_id'      => null,
                            'horario_inicial'  => $horario_inicial,
                            'horario_final'    => $horario_final,
                            'profissional_id'  => $profissional_id,
                            'ambiente_id'      => $ambiente_id,
                            'empresa_id'       => $empresa_id
                        ]);
                    }

                    $msg_multiplos .= "</div>";

                    TSession::setValue('pacientes_seletor',
                    [
                        'pacientes_list'  => $pacientes_list,
                        'horario_inicial' => $horario_inicial,
                        'horario_final'   => $horario_final,
                        'profissional_id' => $profissional_id,
                        'ambiente_id'     => $ambiente_id,
                        'empresa_id'      => $empresa_id
                    ]);

                    TTransaction::close();

                    new TQuestion(
                        $msg_multiplos,
                        $action_sim,
                        new TAction([__CLASS__, 'onCancelaagendamento'])
                    );

                    return;
                }

            if (empty($paciente_id) && $horario_inicial && $profissional_id)
            {
                $data_hora_inicio = DateTime::createFromFormat('Y-m-d H:i:s', $horario_inicial);
                if ($data_hora_inicio)
                {
                    $dataFormatada = $data_hora_inicio->format('Y-m-d');

                    $agendamentos = [];
                    foreach ($pacientes_list as $paciente_id_temp => $paciente_nome)
                    {
                        $agt = Agendamento::where('paciente_id', '=', $paciente_id_temp)
                            ->where('profissional_id', '=', $profissional_id)
                            ->where('horario_inicial', 'like', $dataFormatada . '%')
                            ->load();

                        if (count($agt) > 0)
                        {
                            $agendamentos[$paciente_id_temp] = $agt;
                        }
                    }

                    if (count($agendamentos) > 0)
                    {
                        reset($agendamentos);
                        $paciente_id = key($agendamentos);
                    }
                }
            }

            TTransaction::close();

            // ===== CORREÇÃO INICIADA - 2026-05-13 14:20:00 =====
            // MOTIVO: Validar e sanitizar ALL parâmetros antes de loadPage()  para evitar HTML quebrado e loop infinito

            $clean_params = [];

            // horario_inicial - OBRIGATÓRIO
            if (!empty($horario_inicial)) 
            {
                try 
                {
                    $dt = DateTime::createFromFormat('Y-m-d H:i:s', $horario_inicial);
                    if ($dt && $dt->format('Y-m-d H:i:s') === $horario_inicial) 
                    {
                        $clean_params['horario_inicial'] = $horario_inicial;
                    }
                    else 
                    {
                        throw new Exception('Formato inválido');
                    }
                }
                catch (Exception $e) 
                {
                    TSession::setValue('agendamento_em_processamento', false);
                    throw new Exception('horario_inicial com formato inválido');
                }
            }
            else 
            {
                TSession::setValue('agendamento_em_processamento', false);
                throw new Exception('horario_inicial é obrigatório');
            }

            // horario_final - OPCIONAL
            if (!empty($horario_final)) 
            {
                try 
                {
                    $dt = DateTime::createFromFormat('Y-m-d H:i:s', $horario_final);
                    if ($dt && $dt->format('Y-m-d H:i:s') === $horario_final) 
                    {
                        $clean_params['horario_final'] = $horario_final;
                    }
                    else 
                    {
                        $clean_params['horario_final'] = null;
                    }
                }
                catch (Exception $e) 
                {
                    $clean_params['horario_final'] = null;
                }
            }
            else 
            {
                $clean_params['horario_final'] = null;
            }

            // profissional_id - OBRIGATÓRIO
            if (!empty($profissional_id) && is_numeric($profissional_id)) 
            {
                $clean_params['profissional_id'] = (int)$profissional_id;
            }
            else 
            {
                TSession::setValue('agendamento_em_processamento', false);
                throw new Exception('profissional_id inválido ou vazio');
            }

            // paciente_id - OPCIONAL
            $clean_params['paciente_id'] = (!empty($paciente_id) && is_numeric($paciente_id)) ? (int)$paciente_id : null;

            // ambiente_id - OPCIONAL
            $clean_params['ambiente_id'] = (!empty($ambiente_id) && is_numeric($ambiente_id)) ? (int)$ambiente_id : null;

            // empresa_id - OBRIGATÓRIO
            if (!empty($empresa_id) && is_numeric($empresa_id)) 
            {
                $clean_params['empresa_id'] = (int)$empresa_id;
            }
            else 
            {
                TSession::setValue('agendamento_em_processamento', false);
                throw new Exception('empresa_id inválido ou vazio');
            }

            TSession::setValue('filtro_horariodisponivel', $clean_params);
            TSession::setValue('agendamento_em_processamento', false);
            // CORREÇÃO: Usar loadPage direto sem setTimeout, e forçar limpeza de buffer
            ob_clean();
            TSession::setValue('agendamento_em_processamento', false);
            TApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);        
        } 
        catch (Exception $e) 
        {
            try { TTransaction::rollback(); } catch (Exception $ex) {}
            TSession::setValue('agendamento_em_processamento', false);
            $usuarioLogado = TSession::getValue('username') ?? 'Usuario';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

    public static function bkp_onConfirmMultiplePacientes($param = null)
    {
        try
        {
            // [CORRECAO INICIADA] 2026-05-13 11:37
            // Motivo: Garante que a flag de processamento seja liberada ao confirmar
            // o fluxo iniciado em onOpenCalendarForm, evitando bloqueio permanente.
            TSession::setValue('agendamento_em_processamento', false);
            // [CORRECAO FINALIZADA] 2026-05-13 11:37

            // VALIDAR apenas parmetros REALMENTE obrigatrios paciente_id OPCIONAL
            if (empty($param['horario_inicial']) || empty($param['profissional_id']))
            {
                new TMessage('error', 'Parmetros incompletos para continuar o agendamento (horrio e profissional so obrigatrios)');
                return;
            }

            $clean_params = [
                'empresa_id'      => $param['empresa_id']      ?? null,
                'profissional_id' => $param['profissional_id'] ?? null,
                'paciente_id'     => $param['paciente_id']     ?? null,
                'horario_inicial' => $param['horario_inicial'] ?? null,
                'horario_final'   => $param['horario_final']   ?? null,
                'ambiente_id'     => $param['ambiente_id']     ?? null
            ];

            // Validar formato de horario_inicial
            try
            {
                $dt_inicial = DateTime::createFromFormat('Y-m-d H:i:s', $clean_params['horario_inicial']);
                if (!$dt_inicial)
                {
                    new TMessage('error', 'Formato de data/hora inicial invlido');
                    return;
                }
            }
            catch (Exception $e)
            {
                new TMessage('error', 'Erro ao validar data inicial: ' . $e->getMessage());
                return;
            }

            // Validar formato de horario_final APENAS SE FOI PASSADO
            if (!empty($clean_params['horario_final']))
            {
                try
                {
                    $dt_final = DateTime::createFromFormat('Y-m-d H:i:s', $clean_params['horario_final']);
                    if (!$dt_final)
                    {
                        $clean_params['horario_final'] = null;
                    }
                }
                catch (Exception $e)
                {
                    $clean_params['horario_final'] = null;
                }
            }

            $hora_final_apenas = '';
            if (!empty($clean_params['horario_final']))
            {
                try
                {
                    $dtFim             = new DateTime($clean_params['horario_final']);
                    $hora_final_apenas = $dtFim->format('H:i');
                }
                catch (Exception $e) {}
            }

            $clean_params['vhorario_final'] = $hora_final_apenas;

            TSession::setValue('filtro_horariodisponivel', $clean_params);

            //AdiantiCoreApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);
// CORREÇÃO: Usar loadPage direto sem setTimeout, e forçar limpeza de buffer
ob_clean();
TSession::setValue('agendamento_em_processamento', false);
TApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);            
        }
        catch (Exception $e)
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usurio';
            new TMessage('error', "<b>{$usuarioLogado}</b> - Erro ao confirmar agendamento: {$e->getMessage()}");
        }
    }

    public static function bkp_abrirFormularioComPaciente($param = null)
    {
        try
        {
            // Validar parâmetros básicos
            if (empty($param['horario_inicial']) || empty($param['profissional_id']) || empty($param['paciente_id']))
            {
                new TMessage('error', 'Parâmetros insuficientes para abrir agendamento.');
                return;
            }

            $clean_params = 
            [
                'horario_inicial'  => $param['horario_inicial'],
                'horario_final'    => $param['horario_final']   ?? null,
                'profissional_id'  => $param['profissional_id'],
                'paciente_id'      => $param['paciente_id'],
                'ambiente_id'      => $param['ambiente_id']     ?? null,
                'empresa_id'       => $param['empresa_id']      ?? null
            ];

            //AdiantiCoreApplication::loadPage('AgendamentoCalendarForm02','onShow01',$clean_params);
            ob_clean();
            TSession::setValue('agendamento_em_processamento', false);
            TApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);            
        }
        catch (Exception $e)
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - Erro: {$e->getMessage()}");
        }
    }

    public static function bkp_onConfirmSelectorPaciente($param = null)
    {
        try
        {
            $form_data = TForm::getData('formSelectorPaciente');

            if (empty($form_data->paciente_id_select))
            {
                new TMessage('warning', 'Por favor, selecione um paciente');
                return;
            }

            $data = TSession::getValue('pacientes_seletor');

            if (!$data)
            {
                new TMessage('error', 'Erro ao recuperar dados de sessão');
                return;
            }

            $clean_params = [
                'empresa_id'      => $data['empresa_id'],
                'profissional_id' => $data['profissional_id'],
                'paciente_id'     => $form_data->paciente_id_select,
                'horario_inicial' => $data['horario_inicial'],
                'horario_final'   => $data['horario_final'],
                'ambiente_id'     => $data['ambiente_id']
            ];

            TSession::setValue('filtro_horariodisponivel', $clean_params);

            $hora_final_apenas = '';
            if (!empty($data['horario_final']))
            {
                try
                {
                    $dtFim = new DateTime($data['horario_final']);
                    $hora_final_apenas = $dtFim->format('H:i');
                }
                catch (Exception $e) {}
            }

            $clean_params['vhorario_final'] = $hora_final_apenas;
            TSession::setValue('filtro_horariodisponivel', $clean_params);

            //AdiantiCoreApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);
            // CORREÇÃO: Usar loadPage direto sem setTimeout, e forçar limpeza de buffer
            ob_clean();
            TSession::setValue('agendamento_em_processamento', false);
            TApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);
        }
        catch (Exception $e)
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

    public static function bkp_abrirFormularioAcaoSim($param = null)
    {
        try 
        {
            // Remove parâmetros extras que podem causar problemas
            $clean_params = [];
            $valid_keys = ['empresa_id', 'profissional_id', 'horario_inicial', 'horario_final', 'ambiente_id', 'paciente_id'];

            foreach ($valid_keys as $key) 
            {
                if (isset($param[$key])) 
                {
                    $clean_params[$key] = $param[$key];
                }
            }

            // Usa o método padrão do Adianti para carregar páginas
            //AdiantiCoreApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);            
            // CORREÇÃO: Usar loadPage direto sem setTimeout, e forçar limpeza de buffer
            ob_clean();
            TSession::setValue('agendamento_em_processamento', false);
            TApplication::loadPage('AgendamentoCalendarForm02', 'onShow01', $clean_params);            
        } 
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }
*/