/*
Tenho este arquivo class AgendamentoCalendarForm02 extends TWindow e preciso que as linhas de numero 
87 a 196
4520 a 4822 sejam excluidas devido o builder por algum motivo considerar elas como não acessiveis e ficando no codigo como uma sujeira
*/
/*
VOCÊ ATUARÁ COMO DESENVOLVEDOR SÊNIOR PARA IMPLEMENTAR NOVOS MÉTODOS E CORREÇÕES. 
LEIA AS REGRAS ABAIXO e GRAVE EM SUA MEMORIA, PARA NÃO FICAR FAZENDO PROCESSOS OU PERGUNTAS PARA TOMAR O TEMPO DE FORMA DESNECESSARIA.

CONTEXTO TÉCNICO:
- Linguagem de desenvolvimento: PHP 7.4
- Framework utilizado: MadBuilder (um fork do Adianti Framework)
- Banco de dados: MySQL
- Sistema com estrutura para matriz e múltiplas filiais

RESTRIÇÃO CRÍTICA DE ESCOPO:
- Não há acesso ao servidor.
- Métodos ou trechos comentados no arquivo enviado não são utilizados e devem ser ignorados e não devem ser enviados nas respostas geradas.
- Antes de perguntar se algum método ou função existe, leia integralmente o arquivo enviado.
- Para abrir uma transação com o banco de dados, use obrigatoriamente TTransaction::open(self::$database)
- OS transformers do formulario podem ser modificados se for necessário.
- O ÚNICO BLOCO ONDE É PERMITIDO IMPLEMENTAR NOVOS MÉTODOS, CORREÇÕES ou DEBUG É:
  // COMEÇA AQUI O BLOCO REFATORÁVEL

  // TERMINA AQUI O BLOCO REFATORÁVEL
- TUDO FORA DESSES MARCADORES É INTOCÁVEL. Não altere, não mova, não reescreva nenhuma linha fora desse bloco, mesmo que a solução pareça exigir isso.

PROIBIÇÕES E MANUTENÇÃO DA ARQUITETURA:
É TERMINANTEMENTE PROIBIDO alterar:
- Nomes de variáveis, métodos, classes, campos de formulário, IDs e eventos originais, não suprima codigo, sempre gere completo.
- O fluxo principal existente do sistema.
- Mantenha integralmente a arquitetura existente para garantir compatibilidade reversa.
- NÃO CRIE NOVOS MÉTODOS OU CAMPOS FORA DO BLOCO REFATORÁVEL — PERGUNTE ANTES DE PROSSEGUIR.

PADRÃO DE RESPOSTA:
- Direta, técnica, sem introduções, sem tutoriais e sem pseudocódigo.
- NUNCA gere trechos parciais de código ou substituições manuais (proibido diff).
- NUNCA peça ao usuário para complementar com "o resto do código original".
- Sempre entregue o método, transformer ou bloco refatorável COMPLETO do início ao fim, pronto para copiar e colar, nunca suprima codigo orignal, sempre gere completo.
- Não gere a class completa pergunte antes e explique porque precisa gerar ela toda, so sera gerada com autorização.
- Quando houver dúvida sobre o nome de um campo, tente todas as variações possíveis dentro do próprio código utilizando encadeamento de `elseif` (fallback lógico) antes de perguntar. Só pergunte quando for impossível deduzir.
- Responda estritamente em português do Brasil, utilizando termos técnicos nativos da área de desenvolvimento. Nunca mude para o inglês, a menos que solicitado.
- O código retornado deve manter rigorosamente a mesma indentação do arquivo enviado.

REGRAS DE ENTREGA DO CÓDIGO:
- Destaque dentro do código implementado (via comentários PHP): o que foi feito, a finalidade, a data/hora atual e a assinatura "Gerado por IA".
- Se for gerado alguma implementação ou atualização e caso a mesma não seja utilizada por algum motivo, precisa nos informar para que possarmos retirar ela do codigo, para não ficar codigo no sistema sem utilidade.

DIRETRIZES DE DEBUG (QUANDO SOLICITADO):
- Se for solicitado gerar DEBUG, utilize obrigatoriamente a estrutura para injetar no console do navegador: TScript::create("console.log('=== DEBUG: [identificador] ===');");
- O debug deve cobrir da primeira à última linha do método afetado.
- Numere sequencialmente os logs: debug-nome do metodo 01, debug-nome do metodo 02, etc.
- Não altere a lógica original ao inserir as linhas de debug.
- O código de debug só pode ser removido quando for solicitado explicitamente por escrito.
- Não suprima o codigo original ao fazer alguma atualização, sempre gere o metodo completo.

INSTRUÇÃO FINAL E FLUXO:
- Analise o arquivo enviado completamente antes de emitir qualquer resposta.
- Se o arquivo for muito grande, divida a análise em partes e entregue os resultados de forma modular e organizada.
- Caso chegue à terceira tentativa sem sucesso na solução, sugira obrigatoriamente a inserção do bloco de debug.
- Ao final da resposta, crie um resumo técnico estruturado (o que foi feito, estado atual, pendências e próximo passo exato) formatado como um prompt de continuidade, para que outra IA possa assumir a tarefa sem perda de contexto.

TAREFA:
//-----------------------------------------------------------------------------------

Você atuará como desenvolvedor sênior para implementar novos métodos e fazer correções.

Contexto técnico:
    a) Linguagem de desenvolvimento PHP 7.4
    b) Framework MadBuilder fork do Adianti Framework
    c) Banco de dados MySQL
    d) Sistema com estrutura para matriz e múltiplas filiais

Diretrizes obrigatórias:
    Restrição crítica:
        Não há acesso ao servidor
        Existem metodos ou trechos comentando isso quer dizer que não sõ utilizados e devem ser ignorados.
        Antes de perguntar se algum metodo ou função existe leia o arquivo enviado.
        Para abrir uma transação com o banco este é o padrão do framework TTransaction::open(self::$database); 
        Se não tiver bloco de refatoração não continue, o framework tem restrições de onde ou não pode ser alterado
        Transform podem ser modificados se for necessarios
        A refatoração é permitida dentro do bloco onde começa:
        //Inicio do bloco que pode refatorar ---------------------------------------------------------------------

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

        
    Resposta:
        Direta
        Técnica
        Sem introduções
        Sem tutoriais
        Sem pseudocódigo
        Sem trechos incompletos
        A correção ou implementação do metodo deve ser gerada de forma completa pronto para copiar e principalmente informar onde sera implementada por exemplo metodo onreload

    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:
        A correção ou implementação do metodo deve ser gerada de forma completa pronto para copiar e colar
        Sempre destacar dentro do metodo o que foi implementado e para que finalidade e ainda colocar a data e hora e quem foi que gerou
        Sempre me responda em português do Brasil, utilizando termos técnicos nativos da área de desenvolvimento e programação quando necessário. Nunca mude para o inglês, a menos que eu peça explicitamente.

    Debug:
        Se for solicitado para gerar um DEBUG deve 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 com a versão do framework
        NAO CRIE NOVOS METODOS, CAMPOS, FUNÇÕES PERGUNTE ANTES DE PROSSEGUIR

    Contexto insuficiente:
        Perguntar antes de prosseguir

    Objetivo:
        Corrigir
        Implementar
        Preservar a compatibilidade total com as regras existentes
        
    Instrução final:
        Analise o arquivo enviado
        Não forneça nenhuma solução fora das regras citadas acima.
        Se perceber que a solução proposta não esta funcionando, sugira colocar um debug na terceira tentativa.
        Se o arquivo enviado for considerado grande e para evitar o reinicio a todo momento da geração, divada o processo em partes e vai entregando os resultados
        Me forneca a solução dentro do que foi estabelecido nas regras        
        Crie um resumo detalhado do que já foi feito, o estado atual do projeto, quais são as pendências e qual é o próximo passo exato. Formate isso como um prompt para que outra IA possa continuar o trabalho sem perder o contexto e gere respostas modulares e organizadas.

    Tarefa:

//--------------------------------------------------------------------------------------------------------
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.
//-------------------------------------------------------------------
https://www.scrapy.org/download
https://langsearch.com
https://www.search1api.com/
https://typesense.org/
https://webatendimento.saude.gov.br/
//----------------------------------------------------------------------
//Desabilitar autocomplete
(function() 
{
    function disableAutocompleteForField(field) 
    {
        if (!field || !field.parentNode || field.dataset.processed) return;

        const clone = field.cloneNode(true);

        clone.setAttribute('autocomplete', 'off');
        clone.removeAttribute('id');
        clone.removeAttribute('name');

        // Marca o campo como processado
        field.dataset.processed = 'true';

        // Substitui o campo original após pequeno delay
        setTimeout(function() 
        {
            field.parentNode.replaceChild(clone, field);
        }, 100);
    }

    function processForm(form) 
    {
        if (!form || form.dataset.autocompleteDisabled) return;

        form.setAttribute('autocomplete', 'off');
        form.dataset.autocompleteDisabled = 'true';

        form.querySelectorAll('input[type=text], input[type=password], input[type=email], input[type=tel], textarea')
            .forEach(disableAutocompleteForField);
    }

    function initAntiAutocomplete() 
    {
        document.querySelectorAll('form').forEach(processForm);
    }

    // Executa ao carregar o DOM
    document.addEventListener('DOMContentLoaded', initAntiAutocomplete);

    // Observa mutações no DOM para suportar Adianti (AJAX)
    const observer = new MutationObserver(function(mutations) 
    {
        mutations.forEach(function(mutation) 
        {
            mutation.addedNodes.forEach(function(node) 
            {
                if (node.nodeType === 1) 
                {
                    if (node.tagName === 'FORM') 
                    {
                        processForm(node);
                    } 
                    else 
                    {
                        node.querySelectorAll?.('form').forEach(processForm);
                    }
                }
            });
        });
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();

//----------------------------------------------------
Entendido. O escopo correto é um controle de solicitações médicas para fila de espera e encaixe de pacientes, não um totem de atendimento.

Objetivo do sistema

Registrar solicitações de atendimento, organizar pacientes interessados por especialidade/médico e acompanhar a fila até que uma vaga de encaixe seja disponibilizada.

Fluxo operacional

Recepção/atendente registra a solicitação do paciente, informando especialidade, médico desejado (opcional), prioridade e observações clínicas.

Solicitação entra na fila de espera da especialidade/médico correspondente.

Equipe acompanha o status da solicitação: aguardando, contatado, encaixado, cancelado, não localizado, etc.

Quando surge uma vaga, o sistema permite selecionar o próximo paciente elegível para encaixe.

O paciente é contatado; se confirmar, a solicitação vira encaixe/agendamento. Caso contrário, registra-se a tentativa e segue para o próximo.

O histórico permanece auditável, mostrando quem registrou, quem contatou, quando houve encaixe e o desfecho final.

Dados principais da solicitação

Paciente

Filial

Especialidade

Médico desejado (opcional)

Data da solicitação

Prioridade / urgência

Motivo ou observação clínica

Status atual

Data limite ou preferência de atendimento (opcional)

Responsável pelo cadastro

Status sugeridos

Status

	

Uso no controle




Aguardando

	

Paciente está na fila de espera.




Em análise

	

Equipe verificando disponibilidade.




Contatado

	

Paciente foi chamado para vaga disponível.




Encaixado

	

Vaga confirmada para o paciente.




Agendado

	

Consulta efetivamente marcada.




Não localizado

	

Tentativa de contato sem sucesso.




Cancelado

	

Solicitação encerrada sem encaixe.




Finalizado

	

Fluxo encerrado com atendimento concluído.

Módulos do sistema

Cadastro de solicitações médicas

Fila de espera por especialidade

Fila de espera por médico

Controle de prioridades

Registro de tentativas de contato

Controle de encaixes realizados

Histórico completo da solicitação

Relatórios de demanda reprimida

Relatórios de encaixes por período, médico e filial

Regras de encaixe

Priorizar pacientes conforme data da solicitação, prioridade clínica e preferência por médico.

Permitir encaixe por especialidade quando não houver médico específico solicitado.

Ao encaixar, registrar data/hora da vaga, usuário responsável e resultado do contato.

Evitar encaixe duplicado da mesma solicitação.

Manter histórico de todas as movimentações para auditoria.

Estrutura técnica sugerida

Tabela principal: solicitações médicas.

Tabela de histórico: mudanças de status, contatos e encaixes.

Tabela de prioridades: regras configuráveis pela clínica.

Tabela de vagas/encaixes: quando houver integração com agenda médica.

Compatibilidade com o sistema atual

Manter PHP 7.4, MadBuilder e MySQL.

Usar TTransaction::open(self::$database); para operações de banco.

Respeitar a arquitetura existente, sem alterar nomes de métodos, classes, campos, IDs ou fluxo principal.

Suportar matriz e múltiplas filiais, com filas independentes por unidade.

Resumo técnico (Prompt de Continuidade)

Projeto: Controle de Solicitações Médicas para Fila de Espera e Encaixe de Pacientes.

Escopo correto: Registrar solicitações de pacientes interessados, acompanhar status, controlar prioridades e permitir encaixes quando houver vagas disponíveis.

Fluxo principal: Cadastro da solicitação → fila de espera → análise/contato → encaixe/agendamento → histórico final.

Regras técnicas: PHP 7.4, MadBuilder, MySQL, suporte a múltiplas filiais, uso obrigatório de TTransaction::open(self::$database);, preservação da arquitetura existente e entrega apenas de blocos completos prontos para copiar e colar.

Próximo passo: Receber os arquivos do projeto para implementar cadastro de solicitações, listagem da fila de espera, controle de status, histórico de contatos e rotina de encaixe.

Analisando o arquivo enviado, ele corresponde ao model Agendamento (classe Agendamento extends TRecord) e não à estrutura de uma tabela SQL.

Pelos atributos registrados no addAttribute(), identifiquei que a tabela agendamento já possui praticamente todas as entidades necessárias para integrar futuramente o controle de fila de espera:

Empresa (empresa_id)
Paciente (paciente_id)
Profissional (profissional_id)
Produto/Procedimento (produto_id)
Tipo de agendamento (tipo_agendamento_id)
Origem da consulta (origemconsulta_id)
Ambiente (ambiente_id)
Status
Observações
Datas e usuários de todas as movimentações
Cancelamento
Confirmação
Recepção
Retorno
Finalização
Histórico de auditoria completo
Minha sugestão de arquitetura

Eu não utilizaria a tabela agendamento para representar a fila de espera.

O ideal é criar uma entidade independente, por exemplo:

fila_espera

Ela armazenaria apenas quem ainda não possui agendamento, evitando misturar:

pacientes aguardando vaga;
pacientes já agendados;
pacientes atendidos.

Quando surgir uma vaga:

fila_espera
        │
        ▼
Seleciona paciente
        │
        ▼
Confirma interesse
        │
        ▼
Gera registro em Agendamento

Assim, a tabela Agendamento continua sendo somente agenda, preservando toda a lógica existente do sistema.

Integração

A tabela de fila poderá referenciar exatamente as mesmas entidades já existentes:

empresa_id
paciente_id
profissional_id
produto_id
tipo_agendamento_id
origemconsulta_id

Ou seja, praticamente todas as FKs já existem no sistema.

Também recomendo registrar
Data da solicitação
Prioridade
Ordem da fila
Situação (Aguardando, Contatado, Encaixado, Cancelado...)
Quantidade de tentativas de contato
Última tentativa
Usuário responsável
Observações

Dessa forma, quando um encaixe for confirmado, basta gerar um registro em Agendamento, sem alterar nenhuma regra já existente.

Resumo técnico (Prompt de Continuidade)

Análise realizada: O arquivo enviado é o model Agendamento, que representa a tabela de agenda e possui os relacionamentos necessários (empresa, paciente, profissional, produto, tipo de agendamento, origem da consulta, ambiente e auditoria).

Estado atual: Recomenda-se manter agendamento exclusivamente para consultas agendadas e criar uma entidade separada para a fila de espera, preservando a arquitetura existente.

Pendências: Definir a estrutura da nova tabela de fila de espera e os pontos de integração com o cadastro de agendamentos.

Próximo passo exato: Envie o CREATE TABLE da tabela agendamento (ou o diagrama do banco) e, se já existir, o layout esperado da nova fila. Com isso, elaborarei a estrutura da tabela fila_espera integrada ao modelo atual, mantendo total compatibilidade com o sistema existente.

e isso aqui pacientes aguardando vaga;

Sim, exatamente.

A ideia é que "pacientes aguardando vaga" seja o conceito central da funcionalidade.

Na prática, cada registro representa uma solicitação como estas:

"Quero consulta com cardiologista assim que surgir vaga."
"Pode me encaixar com qualquer ortopedista."
"Quero somente com o Dr. João."
"Se houver desistência, pode me ligar."

Ou seja, não existe horário marcado ainda.

Depois, quando surgir uma vaga por cancelamento, aumento de agenda ou encaixe autorizado, a recepção acessa a fila e visualiza, por exemplo:

Ordem	Paciente	Especialidade	Médico	Data da solicitação	Situação
1	Maria	Cardiologia	Dr. João	01/07	Aguardando
2	José	Cardiologia	Dr. João	02/07	Aguardando
3	Ana	Cardiologia	Qualquer	03/07	Aguardando

Então a recepção:

Seleciona o primeiro da fila.
Faz contato.
Registra o resultado:
Confirmou.
Não atendeu.
Desistiu.
Reagendar contato.
Se confirmar, gera o Agendamento usando a estrutura já existente.
A solicitação da fila passa para Encaixado ou Finalizado.

Assim, a fila funciona como um CRM interno de oportunidades de agendamento, enquanto a tabela agendamento continua armazenando apenas consultas efetivamente marcadas.

Esse modelo preserva a arquitetura atual e evita misturar registros de interesse com agendamentos já confirmados.
//-------------------------------------------------------------------------------

//-----------------------------------------------------------------------------------------------------------
/*
                new TAction([__CLASS__, 'onYesaguardandoconfirmacao'], $param), 
                new TAction([__CLASS__, 'onNaoaguardandoconfirmacao'], $param)
*/
// Não confirmado 
// 02: btn_confirmar 		    	CONFIRMADO
//--------------------------------------------------------------------------------
    public static function onnaoconfirmadoagendamentoYes($param = null)
    {
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            // Validação: Garantir que o ID foi fornecido
            if (!isset($param['id'])) 
            {
                throw new Exception('<br>Agendamento não foi encontrado.');
            }

            $agendamentoId = $param['id'];

            // Inicia a transação
            TTransaction::open(self::$database);
                // Busca o agendamento
                $object = Agendamento::find($agendamentoId); 
                if (!$object) 
                {
                    TTransaction::rollback();
                    throw new Exception("<br>Agendamento {$agendamentoId} não encontrado.");
                }

                // Atualizar os campos
                $object->status                = '05';  // Confirmado
                $object->data_naoconfirmado    = date('Y-m-d');
                $object->hora_naoconfirmado    = date('H:i');
                $object->usuario_naoconfirmado = TSession::getValue('userid');
                $object->store();
            TTransaction::close();

            // Recarregar o objeto para garantir valores atualizados do banco
            TTransaction::open(self::$database);
                $object = Agendamento::find($agendamentoId);
            TTransaction::close();

            // Preparar o objeto com formatações corretas para exibição
            self::formatardatas($object);

            // Ajustar botões de forma eficiente
            TButton::enableField(self::$formName,  'btn_confirmado');
            TButton::disableField(self::$formName, 'btn_naoconfirmado');
            TButton::disableField(self::$formName, 'btn_naocompareceu');
            TButton::disableField(self::$formName, 'btn_recepcao');
            TButton::disableField(self::$formName, 'btn_finalizar');
            TButton::disableField(self::$formName, 'btn_retorno');
            TButton::disableField(self::$formName, 'btn_duplicar');
            TButton::enableField(self::$formName,  'btn_cancelar');
            TButton::disableField(self::$formName, 'btn_protocoloepreparo');
            TButton::disableField(self::$formName, 'btn_calcularnovadataagendamento');
            TButton::disableField(self::$formName, 'btn_listagemagendamento');
            TButton::disableField(self::$formName, 'btn_atualizardadospaciente');
            TButton::disableField(self::$formName, 'btn_visualizarconvenioprofissional');            
            TButton::disableField(self::$formName, 'btn_pacientenovo');
            TButton::disableField(self::$formName, 'btn_verificafinanceiro');
            TButton::disableField(self::$formName, 'btn_copiarnumeocarterinha');
            TButton::disableField(self::$formName, 'btn_atualizasaladeatendimento');
            TButton::disableField(self::$formName, 'btn_atualizavalores');

            TSpinner::disableField(self::$formName,    'ordematendimento');
            THtmlEditor::disableField(self::$formName, 'observacao');
            TDBCombo::disableField(self::$formName,    'ambiente_id');
            TDBCombo::disableField(self::$formName,    'equipamento_id');
            TEntry::disableField(self::$formName,      'agendamento_anexos_agendamento_descricao_anexo');
            TFile::disableField(self::$formName,       'agendamento_anexos_agendamento_arquivo_anexado');

            // Atualizar formulário SEM disparar eventos onChange (isso é a chave!)
            TForm::sendData(self::$formName, $object, false, false); // false, false = não dispara eventos

            // Atualizar APENAS o campo status diretamente via JavaScript de forma otimizada
            TScript::create("
                (function(){
                    var statusField = document.querySelector('[name=\"status\"]');
                    if (statusField) 
                    {
                        statusField.value = '{$object->status}';
                    }
                })();
            ");

            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            TToast::show("show", "{$usuarioLogado}<br> Agendamento não confirmado, clique no botão salvar para continuar.", "topRight", "fas:info-circle");
        }
        catch (Exception $e) 
        {
            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
            TTransaction::rollback();
        }
    }

    public static function onNaoconfirmadoagendamentoNo($param = null) 
    {
        try 
        {
            //code here
        }
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }
//-----------------------------------------------------------------------------------------------------------
//Confirmado-------------------------------------------------------------------------------------------------
    public static function onconfirmaragendamentoYes($param = null)
    {
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            // Validação: Garantir que o ID foi fornecido
            if (!isset($param['id'])) 
            {
                throw new Exception('<br>Agendamento não foi encontrado.');
            }

            $agendamentoId = $param['id'];

            // Inicia a transação
            TTransaction::open(self::$database);
                // Busca o agendamento
                $object = Agendamento::find($agendamentoId); 
                if (!$object) 
                {
                    TTransaction::rollback();
                    throw new Exception("<br>Agendamento {$agendamentoId} não encontrado.");
                }

                // Atualizar os campos
                $object->status              = '02';  // Confirmado
                $object->data_confirmacao    = date('Y-m-d');
                $object->hora_confirmacao    = date('H:i');
                $object->usuario_confirmacao = TSession::getValue('userid');
                $object->store();
            TTransaction::close();

            // Recarregar o objeto para garantir valores atualizados do banco
            TTransaction::open(self::$database);
                $object = Agendamento::find($agendamentoId);
            TTransaction::close();

            // Preparar o objeto com formatações corretas para exibição
            self::formatardatas($object);

            // Ajustar botões de forma eficiente
            TButton::disableField(self::$formName, 'btn_confirmado');
            TButton::disableField(self::$formName, 'btn_naoconfirmado');
            TButton::enableField(self::$formName,  'btn_naocompareceu');
            TButton::enableField(self::$formName,  'btn_recepcao');
            TButton::disableField(self::$formName, 'btn_finalizar');
            TButton::disableField(self::$formName, 'btn_retorno');
            TButton::disableField(self::$formName, 'btn_duplicar');
            TButton::enableField(self::$formName,  'btn_cancelar');
            TButton::enableField(self::$formName,  'btn_protocoloepreparo');
            TButton::disableField(self::$formName, 'btn_calcularnovadataagendamento');
            TButton::disableField(self::$formName, 'btn_listagemagendamento');
            TButton::enableField(self::$formName,  'btn_atualizardadospaciente');
            TButton::enableField(self::$formName,  'btn_visualizarconvenioprofissional');
            TButton::disableField(self::$formName, 'btn_pacientenovo');
            TButton::disableField(self::$formName, 'btn_verificafinanceiro'); //verificar
            TButton::enableField(self::$formName,  'btn_copiarnumeocarterinha');
            TButton::disableField(self::$formName, 'btn_atualizasaladeatendimento');
            TButton::disableField(self::$formName, 'btn_atualizavalores');

            // Atualizar formulário SEM disparar eventos onChange (isso é a chave!)
            TForm::sendData(self::$formName, $object, false, false); // false, false = não dispara eventos

            // Atualizar APENAS o campo status diretamente via JavaScript de forma otimizada
            TScript::create("
                (function(){
                    var statusField = document.querySelector('[name=\"status\"]');
                    if (statusField) 
                    {
                        statusField.value = '{$object->status}';
                    }
                })();
            ");

            // Mensagem de sucesso
            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            TToast::show("show", "{$usuarioLogado}<br> Agendamento confirmado, clique no botão salvar para continuar.", "topRight", "fas:info-circle");
        }
        catch (Exception $e) 
        {
            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
            TTransaction::rollback();
        }
    }

    public static function onconfirmaragendamentoNo($param = null) 
    {
        try 
        {
            //code here
        }
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }
//Não compareceu-------------------------------------------------------------------------------
    public static function onnaocompareceuYes($param = null)
    {
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            if (!isset($param['id'])) 
            {
                throw new Exception('<br>ID do agendamento não foi encontrado.');
            }

            $agendamentoId = $param['id'];

            // Inicia a transação
            TTransaction::open(self::$database);
                // Busca o agendamento
                $object = Agendamento::find($agendamentoId); 
                if (!$object) 
                {
                    TTransaction::rollback();
                    throw new Exception("<br>Agendamento com ID {$agendamentoId} não encontrado.");
                }

                // Atualizar os campos
                $object->status                = '04';  // NÃO COMPARECEU
                $object->data_naocompareceu    = date('Y-m-d');
                $object->hora_naocompareceu    = date('H:i');
                $object->usuario_naocompareceu = TSession::getValue('userid');
                $object->store();
            TTransaction::close();

            // Recarregar o objeto para garantir valores atualizados do banco
            TTransaction::open(self::$database);
                $object = Agendamento::find($agendamentoId);
            TTransaction::close();

            // Preparar o objeto com formatações corretas para exibição
            self::formatardatas($object);

            TButton::disableField(self::$formName, 'btn_confirmado');
            TButton::disableField(self::$formName, 'btn_naoconfirmador');            
            TButton::disableField(self::$formName, 'btn_naocompareceu');
            TButton::disableField(self::$formName, 'btn_recepcao');
            TButton::disableField(self::$formName, 'btn_finalizar');
            TButton::disableField(self::$formName, 'btn_retorno');
            TButton::enableField(self::$formName,  'btn_duplicar');
            TButton::disableField(self::$formName, 'btn_cancelar');
            TButton::disableField(self::$formName, 'btn_protocoloepreparo');
            TButton::disableField(self::$formName, 'btn_calcularnovadataagendamento');
            TButton::disableField(self::$formName, 'btn_listagemagendamento');
            TButton::disableField(self::$formName, 'btn_atualizardadospaciente');
            TButton::disableField(self::$formName, 'btn_visualizarconvenioprofissional');            
            TButton::disableField(self::$formName, 'btn_pacientenovo');
            TButton::disableField(self::$formName, 'btn_verificafinanceiro');
            TButton::disableField(self::$formName, 'btn_copiarnumeocarterinha');
            TButton::disableField(self::$formName, 'btn_atualizasaladeatendimento');
            TButton::disableField(self::$formName, 'btn_atualizavalores');

            THtmlEditor::disableField(self::$formName, 'observacao');
            TSpinner::disableField(self::$formName, 'ordematendimento');
            TDBCombo::disableField(self::$formName, 'ambiente_id');

            TForm::sendData(self::$formName, $object);

            TField::setValue('status', $object->status);

            $js = "document.getElementsByName('status')[0].value = '{$object->status}';";
            TPage::getPage()->onLoad($js);

            $userName = TSession::getValue('username');
            new TMessage('info', "<b>{$userName}</b> - Status 'Não compareceu' confirmado com sucesso!");
        }
        catch (Exception $e) 
        {
            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
            TTransaction::rollback(); // undo all pending operations
        }
    }

    public static function onnaocompareceuNo($param = null) 
    {
        try 
        {
            //code here
        }
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

//Cancelar-----------------------------------------------------------------------------------------
    public static function oncancelarYes($param = null)
    {
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            TTransaction::open(self::$database);
            $check = new Agendamento($param['id']);
            if ($check->cancelado == 'S') 
            {
                throw new Exception("Este agendamento já está cancelado.");
            }
            TTransaction::close();

            // Se o motivo ainda não foi enviado, abre a janela para perguntar
            if (!isset($param['confirmar_processo']) || $param['confirmar_processo'] != '1') 
            {
                $window = TWindow::create('CANCELAR AGENDAMENTO', 600, null);
                $form   = new BootstrapFormBuilder('input_form_cancelar_agendamento');
                $form->setProperty('style', 'border:none; box-shadow:none; background-color:white;');

                $vcancelamento = new TEntry('cancelamento'); // Campo onde o usuário digita o motivo
                $vcancelamento->setSize('100%'); 

                // --- AJUSTE AQUI: Força o estilo visual e o comportamento de digitação ---
                $vcancelamento->setProperty('style', 'text-transform: uppercase');
                $vcancelamento->setProperty('onkeyup', "this.value = this.value.toUpperCase()");

                // Hidden para manter o ID
                $h_id = new THidden('id'); 
                $h_id->setValue($param['id']);

                // Hidden para sinalizar que agora pode processar
                $h_confirm = new THidden('confirmar_processo');
                $h_confirm->setValue('1');

                $label01 = new TLabel("INFORME O MOTIVO DO CANCELAMENTO:");
                $label01->setFontColor('#F44336'); 
                $label01->setFontStyle('b');

                $form->addFields([$label01]);
                $form->addFields([$vcancelamento, $h_id, $h_confirm]);

                $form->addAction('Confirmar', new TAction([__CLASS__, 'onConfirmarCancelamento']), 'fa:check green');            // 2) Se apertar o botão confirmar executa o processo
                $form->addAction('Cancelar',  new TAction([__CLASS__, 'onCloseWindow']), 'fa:times red');                        // 2) Se não (Cancelar/Fechar), fecha a tela e não faz nada

                $container          = new TElement('div');
                $container->style   = "background-color:white; padding:25px; border-radius:5px;";
                $container->add($form);
                TScript::create("$('.panel-footer').css('background-color', 'white').css('border-top', 'none');");

                $window->add($form);
                $window->show();
                return;
            }
        }
        catch (Exception $e) 
        {
            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

    public static function oncancelarNo($param = null) 
    {
        try 
        {
            //code here
        }
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

    public static function onConfirmarCancelamento($param = null)
    {
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            if (!isset($param['id'])) 
            {
                throw new Exception('<br>Agendamento não foi encontrado.');
            }

            if (empty($param['cancelamento']))
            {
                throw new Exception("<br>O motivo do cancelamento é obrigatório!");
            }

            $id           = $param['id']; 
            $hora_agora   = date('H:i');
            $data_agora   = date('Y-m-d');
            $usuario_id   = TSession::getValue('userid');
            $usuario_nome = TSession::getValue('username');

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

            $agendamento = Agendamento::find($id);

            if (!$agendamento)
            {
                throw new Exception("Agendamento {$id} não encontrado.");
            }

            // RESTAURA GUIA (ADICIONADO)
            if (!empty($agendamento->guia_auxiliar_id))
            {
                $guia_item = new GuiasconvenioItem($agendamento->guia_auxiliar_id);

                if (!empty($guia_item->guia_conveniocab_id))
                {
                    $guia_cab = new GuiasconvenioCab($guia_item->guia_conveniocab_id);

                    $guia_cab->guia_saldo = $guia_cab->guia_saldo + 1;
                    $guia_cab->store();
                }

                $guia_item->status    = 'A';
                $guia_item->utilizado = 'N';
                $guia_item->store();
            }

            // SEU BLOCO ORIGINAL (AJUSTADO)
            $contas = Conta::where('agendamento_id', '=', $id)->load();

            if ($contas)
            {
                foreach ($contas as $conta)
                {
                    if ($conta->quitada == 'S')
                    {
                        throw new Exception("Não é possível cancelar, existe um financeiro quitado para este agendamento.");
                    }

                    // AJUSTE AQUI
                    $conta->cancelado            = 'C';
                    $conta->tipo_cancelamento    = 1;
                    $conta->usuario_cancelamento = $usuario_id;
                    $conta->data_cancelamento    = $data_agora;
                    $conta->hora_cancelamento    = $hora_agora;

                    $conta->motivo_cancelamento  = $param['cancelamento'];
                    $conta->store();
                }
            }

            // SEU BLOCO ORIGINAL (INALTERADO)
            $agendamento->cancelado            = 'S';
            $agendamento->motivo_cancelamento  = $param['cancelamento'];
            $agendamento->data_cancelamento    = $data_agora;
            $agendamento->hora_cancelamento    = $hora_agora;
            $agendamento->usuario_cancelamento = $usuario_id;
            $agendamento->store();

            TTransaction::close();

            self::formatardatas($agendamento);

            $data                            = new stdClass;
            $data->cancelado                 = 'S';
            $data->status                    = $agendamento->status;
            $data->motivo_cancelamento       = $param['cancelamento'];
            $data->data_cancelamento         = TDate::date2br($data_agora);
            $data->hora_cancelamento         = $hora_agora;
            $data->usuario_cancelamento_nome = $usuario_nome;

            THtmlEditor::disableField(self::$formName, 'observacao');
            TDBCombo::disableField(self::$formName,    'ambiente_id');
            TSpinner::disableField(self::$formName,    'ordematendimento');
            TButton::disableField(self::$formName,     'btn_confirmado');
            TButton::disableField(self::$formName,     'btn_naoconfirmado');
            TButton::disableField(self::$formName,     'btn_naocompareceu');
            TButton::disableField(self::$formName,     'btn_recepcao');
            TButton::disableField(self::$formName,     'btn_finalizar');
            TButton::disableField(self::$formName,     'btn_retorno');
            TButton::disableField(self::$formName,     'btn_duplicar');
            TButton::disableField(self::$formName,     'btn_cancelar');
            TButton::disableField(self::$formName,     'btn_protocoloepreparo');
            TButton::disableField(self::$formName,     'btn_calcularnovadataagendamento');
            TButton::disableField(self::$formName,     'btn_listagemagendamento');
            TButton::disableField(self::$formName,     'btn_atualizardadospaciente');
            TButton::disableField(self::$formName,     'btn_visualizarconvenioprofissional');            
            TButton::disableField(self::$formName,     'btn_pacientenovo');
            TButton::disableField(self::$formName,     'btn_verificafinanceiro');
            TButton::disableField(self::$formName,     'btn_copiarnumeocarterinha');
            TButton::disableField(self::$formName,     'btn_atualizasaladeatendimento');
            TButton::disableField(self::$formName,     'btn_atualizavalores');

            TForm::sendData(self::$formName, $data);

            AgendamentoList::manageRow($id);

            TWindow::closeWindow(); 

            new TMessage('info', "{$usuario_nome}<br>Agendamento e títulos financeiros cancelados com sucesso!");

        }
        catch (Exception $e) 
        {
            TTransaction::rollback();
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> {$e->getMessage()}");
        }
    }

    //Confirmar recepção--------------------------------------------------------------------------------------------

    public static function onconfirmarrecepcaoYes($param = null) 
    {
        //Inicio do bloco que pode refatorar ---------------------------------------------------------------------
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            if (!isset($param['id'])) 
            {
                throw new Exception('<br>Agendamento não foi encontrado.');
            }

            $agendamentoId = $param['id'];

            TTransaction::open(self::$database);
                $object = Agendamento::find($agendamentoId); 
                if (!$object) 
                {
                    TTransaction::rollback();
                    throw new Exception("<br>Agendamento {$agendamentoId} não encontrado.");
                }

                $object->status           = '97';
                $object->data_recepcao    = date('Y-m-d');
                $object->hora_recepcao    = date('H:i');
                $object->usuario_recepcao = TSession::getValue('userid');
                $object->store();
            TTransaction::close();

            $pessoa_profissional = null;
            TTransaction::open(self::$database);
                $pessoa_profissional = Pessoa::where('usuario_sistema', '=', $object->profissional_id)->first();
                $pessoa_paciente     = Pessoa::find($object->paciente_id);
            TTransaction::close();

            if ($pessoa_profissional && !empty($pessoa_profissional->usuario_sistema))
            {
                $nome_paciente    = $pessoa_paciente ? $pessoa_paciente->nome : 'Paciente não identificado';
                $user_id          = $pessoa_profissional->usuario_sistema;
                $action_btn       = new TAction(['AgendamentoCalendarForm02', 'onEdit']);
                $action_btn->setParameter('id', $object->id);
                $icon             = 'fa-user-check';
                $data_notificacao = date('Y/m/d H:i');
                $titulo           = 'PACIENTE AGUARDANDO NA RECEPÇÃO';
                $texto            = "O PACIENTE: {$nome_paciente}<br>HORÁRIO: {$object->horario_inicial} REFERENTE AO AGENDAMENTO nº {$object->id}<br>PARA DESABILITAR A MENSAGEM CLIQUE NO BOTÃO OK";
                $texto_btn        = 'Visualizar agendamento';

                SystemNotification::register($user_id, $titulo, $texto, $action_btn, $texto_btn, $icon, $data_notificacao, $object->id);
            }
            // [FIM CORREÇÃO]

            TTransaction::open(self::$database);
                $object = Agendamento::find($agendamentoId);
            TTransaction::close();

            self::formatardatas($object);

            TButton::disableField(self::$formName, 'btn_confirmado');
            TButton::disableField(self::$formName, 'btn_naoconfirmado');            
            TButton::disableField(self::$formName, 'btn_naocompareceu');
            TButton::disableField(self::$formName, 'btn_recepcao');
            TButton::enableField(self::$formName,  'btn_finalizar');
            TButton::disableField(self::$formName, 'btn_retorno');
            TButton::disableField(self::$formName, 'btn_duplicar');
            TButton::disableField(self::$formName, 'btn_cancelar');
            TButton::disableField(self::$formName, 'btn_protocoloepreparo');
            TButton::disableField(self::$formName, 'btn_calcularnovadataagendamento');
            TButton::disableField(self::$formName, 'btn_listagemagendamento');
            TButton::disableField(self::$formName, 'btn_atualizardadospaciente');
            TButton::disableField(self::$formName, 'btn_visualizarconvenioprofissional');            
            TButton::disableField(self::$formName, 'btn_pacientenovo');
            TButton::disableField(self::$formName, 'btn_verificafinanceiro');
            TButton::disableField(self::$formName, 'btn_copiarnumeocarterinha');
            TButton::disableField(self::$formName, 'btn_atualizasaladeatendimento');
            TButton::disableField(self::$formName, 'btn_atualizavalores');

            THtmlEditor::disableField(self::$formName, 'observacao');
            TSpinner::disableField(self::$formName, 'ordematendimento');
            TDBCombo::disableField(self::$formName, 'ambiente_id');

            TForm::sendData(self::$formName, $object, false, false);

            TScript::create("
                (function()
                {
                    var statusField = document.querySelector('[name=\"status\"]');
                    if (statusField) 
                    {
                        statusField.value = '{$object->status}';
                    }
                })();
            ");

            $nome_profissional     = ($pessoa_profissional) ? $pessoa_profissional->nome : 'Profissional não identificado';
            $aviso_usuario_sistema = ($pessoa_profissional && empty($pessoa_profissional->usuario_sistema))
                ? '<br><b style="color:red;">⚠ Atenção: usuário do sistema não foi parametrizado no cadastro do profissional. Notificação não enviada.</b>'
                : '';
            TToast::show("show", "{$usuarioLogado}<br> Confirmado que o paciente esta aguardando na recepção,<br> clique no botão salvar para continuar.<br> Enviando aviso ao Profissional: <b>{$nome_profissional}</b>{$aviso_usuario_sistema}", "topRight", "fas:info-circle");

        }
        catch (Exception $e) 
        {
            TTransaction::rollback();
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

    public static function onconfirmarrecepcaoNo($param = null) 
    {
        try 
        {
            //code here
        }
        catch (Exception $e) 
        {
            // Usando interpolação de strings para melhor legibilidade
            $usuarioLogado = TSession::getValue('username');
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

//Finalizar --------------------------------------------------------------------------------------------
    public static function onfinalizarYes($param = null)
    {
        try 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';

            if (!isset($param['id'])) 
            {
                throw new Exception('<br>Agendamento não foi encontrado.');
            }

            $agendamentoId = $param['id'];

            // Inicia a transação
            TTransaction::open(self::$database);
                // Busca o agendamento
                $object = Agendamento::find($agendamentoId); 
                if (!$object) 
                {
                    TTransaction::rollback();
                    throw new Exception("<br>Agendamento {$agendamentoId} não encontrado.");
                }
                $object->status              = '12'; //FINALIZADO
                $object->data_finalizacao    = date('Y-m-d');
                $object->hora_finalizacao    = date('H:i');
                $object->usuario_finalizacao = TSession::getValue('userid');
                $object->finalizado          = 'S';
                $object->store();

            TTransaction::close();

            // Recarregar o objeto para garantir valores atualizados do banco
            TTransaction::open(self::$database);
                $object = Agendamento::find($agendamentoId);
            TTransaction::close();

            // Preparar o objeto com formatações corretas para exibição
            self::formatardatas($object);

            TButton::disableField(self::$formName, 'btn_confirmado');
            TButton::disableField(self::$formName, 'btn_naoconfirmado');
            TButton::disableField(self::$formName, 'btn_naocompareceu');
            TButton::disableField(self::$formName, 'btn_recepcao');
            TButton::disableField(self::$formName, 'btn_finalizar');
            TButton::disableField(self::$formName, 'btn_retorno');
            TButton::enableField(self::$formName,  'btn_duplicar');
            TButton::disableField(self::$formName, 'btn_cancelar');
            TButton::disableField(self::$formName, 'btn_protocoloepreparo');
            TButton::disableField(self::$formName, 'btn_calcularnovadataagendamento');
            TButton::disableField(self::$formName, 'btn_listagemagendamento');
            TButton::disableField(self::$formName, 'btn_atualizardadospaciente');
            TButton::disableField(self::$formName, 'btn_visualizarconvenioprofissional');
            TButton::disableField(self::$formName, 'btn_pacientenovo');
            TButton::disableField(self::$formName, 'btn_verificafinanceiro');
            TButton::disableField(self::$formName, 'btn_copiarnumeocarterinha');
            TButton::disableField(self::$formName, 'btn_atualizasaladeatendimento');
            TButton::disableField(self::$formName, 'btn_atualizavalores');

            // Atualizar formulário SEM disparar eventos onChange (isso é a chave!)
            TForm::sendData(self::$formName, $object, false, false); // false, false = não dispara eventos

            // Atualizar APENAS o campo status diretamente via JavaScript de forma otimizada
            TScript::create("
                (function()
                {   var statusField = document.querySelector('[name=\"status\"]');
                    if (statusField) 
                    {
                        statusField.value = '{$object->status}';
                    }
                })();
            ");

            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            TToast::show("show", "{$usuarioLogado}<br>Agendamento finalizado, clique no botão salvar para continuar.", "topRight", "fas:info-circle");
        }
        catch (Exception $e) 
        {
            //$usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
            TTransaction::rollback(); // undo all pending operations
        }
    }

    public static function onfinalizarNo($param = null) 
    {
        try 
        {
            //code here
        }
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

//Duplicar------------------------------------------------------------------------------------------------
    public static function onduplicarYes($param = null)
    {
        try 
        {
            $userName        = TSession::getValue('username');
            $horario_inicial = $param['horario_inicial'] ?? '';
            $vhorario_final  = $param['vhorario_final']  ?? '';

            if (empty($param['id'])) 
            {
                throw new \Exception(($userName ?? 'Usuário') . ' - ID do agendamento não informado.');
            }

            if (empty($horario_inicial) || empty($vhorario_final)) 
            {
                throw new \Exception("Os campos Data e Hora inicial e Data e hora final precisam estar preenchidos.");
            }

            // Duplicação final
            if ((isset($param['dias']) && trim((string)$param['dias']) !== '' && (int)$param['dias'] > 0) ||
                (isset($param['nova_data']) && !empty(trim($param['nova_data']))))
            {
                $agendamentoClone = self::prepararDuplicacao($param);

                if ($agendamentoClone && $agendamentoClone->id)
                {
                    new TMessage('info', '<b>' . TSession::getValue('username') . '</b><br>Agendamento ' . $param['id'] . ' foi duplicado.<br>Faça as alterações necessárias e salve.');

                    parent::closeWindow();

                    TApplication::loadPage('AgendamentoCalendarForm02', 'onEdit', [
                        'key'                  => $agendamentoClone->id,
                        'duplicado'            => 'true',
                        'agendamento_original' => $param['id']
                    ]);
                }
                return;
            }

            // Janela de cálculo
            $dias_sugeridos        = null;
            $data_previsao_inicial = '';

            try
            {
                TTransaction::open(self::$database);
                $agendamento = new Agendamento($param['id']);
                if (!empty($agendamento->paciente_id)) 
                {
                    $pessoa = new Pessoa($agendamento->paciente_id);
                    if ($pessoa && !empty($pessoa->sessoes_frequenciaemdias)) 
                    {
                        $dias_sugeridos = (int)$pessoa->sessoes_frequenciaemdias;
                    }
                }
                TTransaction::close();
            }
            catch (\Throwable $e) 
            {
                if (TTransaction::isOpen(self::$database)) TTransaction::rollback();
            }

            if (!empty($horario_inicial) && $dias_sugeridos > 0) 
            {
                $data_previsao_inicial = self::calcularPrevisaoData($horario_inicial, $dias_sugeridos);
            }

            $window = TWindow::create('CALCULAR A NOVA DATA DE AGENDAMENTO', 550, null);
            $form   = new BootstrapFormBuilder('form_calcular_dias');
            $form->setProperty('style', 'border:none; box-shadow:none; background-color:white; padding:20px;');

            // Seção 1: Quantidade de dias
            $label_dias = new TLabel('<strong>Quantidade de dias:</strong>', '#333333', '13px');

            $dias = new TEntry('dias');
            $dias->setValue($dias_sugeridos);
            $dias->setSize('100%');
            $dias->setProperty('placeholder', 'Digite a quantidade de dias');
            $dias->{'onkeypress'} = "if (event.keyCode == 13) { \$(this).blur(); return false; }";            
            $dias->setExitAction(new TAction([__CLASS__, 'onAtualizarPrevisao01']));

            $divisor = new TElement('div');
            $divisor->setProperty('style', 'margin: 20px 0;');
            $divisor->add('<hr style="border: 0; border-top: 1px solid #ccc;">');
            $divisor->add('<label style="color: #1976d2; font-size: 13px;"><strong>— OU SELECIONE A DATA DIRETAMENTE NO CALENDÁRIO —</strong></label>');

            // Seção 2: Nova data
            $label_nova_data = new TLabel('<strong>Nova data:</strong>', '#333333', '13px');

            $nova_data = new TDate('nova_data');
            $nova_data->setSize('100%');
            $nova_data->setMask('dd-mm-yyyy');
            $nova_data->setDatabaseMask('yyyy-mm-dd');
            $nova_data->setValue(date('d-m-Y'));

            // Seção 3: Data prevista (calculada)
            $label_previsao = new TLabel('<strong>Data prevista:</strong>', '#333333', '13px');

            $previsao_data = new TEntry('previsao_data');
            $previsao_data->setValue($data_previsao_inicial);
            $previsao_data->setSize('100%');
            $previsao_data->setEditable(false);
            $previsao_data->setProperty('style', 'background-color:#e8f4fd; font-weight:bold; border:2px solid #1976d2; padding:10px; border-radius:4px; font-size:13px;');

            // Hidden fields
            $h_id  = new THidden('id');              $h_id->setValue($param['id']);
            $h_ini = new THidden('horario_inicial'); $h_ini->setValue($horario_inicial);
            $h_fim = new THidden('vhorario_final');  $h_fim->setValue($vhorario_final);

            // Montagem do formulário
            $form->addFields([$label_dias]);
            $form->addFields([$dias]);
            $form->addFields([$divisor]);
            $form->addFields([$label_nova_data]);
            $form->addFields([$nova_data]);
            $form->addFields([$label_previsao]);
            $form->addFields([$previsao_data]);
            $form->addFields([$h_id, $h_ini, $h_fim]);

            $form->addAction('Confirmar', new TAction([__CLASS__, 'onduplicarYes']), 'fa:check green');
            $form->addAction('Cancelar',  new TAction([__CLASS__, 'onCloseWindow']),  'fa:times red');

            $container = new TElement('div');
            $container->add($form);

            // Chamada segura
            TScript::create("
                setTimeout(function(){
                    \$('input[name=\"nova_data\"]').on('change dp.change', function(){
                        var valor = \$(this).val();
                        if (valor && valor.length >= 8) {
                            __adianti_ajax_exec('class=AgendamentoCalendarForm02&method=onAtualizarPrevisao01&static=1&nova_data=' + encodeURIComponent(valor) + '&horario_inicial=" . addslashes($horario_inicial) . "');
                        }
                    });
                }, 800);
            ");

            $window->add($container);
            $window->show();
        } 
        catch (Exception $e) 
        {
            new TMessage('error', '<b>' . (TSession::getValue('username') ?? 'Usuário') . '</b> - ' . $e->getMessage());
        }
    }


    public static function onduplicarNo($param = null) 
    {
        try 
        {
            // Não faz nada, apenas fecha
        } 
        catch (Exception $e) 
        {
            $usuarioLogado = TSession::getValue('username') ?? 'Usuário';
            new TMessage('error', "<b>{$usuarioLogado}</b> - {$e->getMessage()}");
        }
    }

    private static function prepararDuplicacao($param)
    {
        try {
            TTransaction::open(self::$database);

            if (empty($param['id'])) {
                throw new Exception(TSession::getValue('username') . ' - ID do agendamento não informado.');
            }

            if (!isset($param['dias']) || trim($param['dias']) === '' || (int)$param['dias'] <= 0) {
                throw new Exception('Quantidade de dias inválido. Por favor, informe um valor maior que zero.');
            }

            $agendamento = Agendamento::find($param['id']);
            if (!$agendamento) {
                throw new Exception(TSession::getValue('username') . ' - Agendamento não encontrado para duplicar.');
            }

            $dias     = (int) $param['dias'];
            $horarios = self::calcularProximoDiaSemana($agendamento->horario_inicial, $agendamento->horario_final, $dias);

            if (!$horarios || empty($horarios['inicio'])) {
                throw new Exception('Não foi possível calcular a nova data do agendamento.');
            }

            // Clone do agendamento
            $agendamentoClone = new Agendamento();
            $dados            = $agendamento->toArray();
            unset($dados['id']);

            // Ajustes do novo agendamento
            $dados['agendamento_anterior']   = $agendamento->id;

            $dt_inicio_original = DateTime::createFromFormat('Y-m-d H:i:s', $agendamento->horario_inicial);
            if (!$dt_inicio_original) {
                $dt_inicio_original = DateTime::createFromFormat('Y-m-d H:i', $agendamento->horario_inicial);
            }

            $dt_fim_original = DateTime::createFromFormat('Y-m-d H:i:s', $agendamento->horario_final);
            if (!$dt_fim_original) {
                $dt_fim_original = DateTime::createFromFormat('Y-m-d H:i', $agendamento->horario_final);
            }

            $duracao_segundos = $dt_fim_original->getTimestamp() - $dt_inicio_original->getTimestamp();
            $novo_inicio      = clone $dt_inicio_original;
            $novo_inicio->modify("+{$dias} days");
            $novo_fim         = clone $novo_inicio;
            $novo_fim->modify("+{$duracao_segundos} seconds");

            $dados['horario_inicial']               = $novo_inicio->format('Y-m-d H:i:s');
            $dados['horario_final']                 = $novo_fim->format('Y-m-d H:i:s');
            $dados['vhorario_final']                = null;
            $dados['guia_conveniocab_id']           = null;
            $dados['guia_auxiliar_id']              = null;
            $dados['ambiente_id']                   = null;
            $dados['observacao']                    = null;
            $dados['ordematendimento']              = null;
            $dados['status']                        = '01';
            $dados['finalizado']                    = 'N';
            $dados['cancelado']                     = 'N';
            $dados['geroudesconto']                 = 'N';
            $dados['geroufinanceiro']               = 'N';
            $dados['geroudesconto_id']              = null;
            $dados['motivo_cancelamento']           = null;
            $dados['cobranca_id']                   = $agendamento->cobranca_id;
            $dados['entrega_resultado']             = $agendamento->entrega_resultado;
            $dados['valor_taxaentregaexame']        = $agendamento->valor_taxaentregaexame;
            $dados['valor_venda']                   = $agendamento->valor_venda;
            $dados['valor_receber']                 = $agendamento->valor_receber;
            $dados['percentual_desconto_maximo']    = $agendamento->percentual_desconto_maximo;
            $dados['percentual_desconto_utilizado'] = $agendamento->percentual_desconto_utilizado;
            $dados['data_inclusao']                 = date('Y-m-d');
            $dados['hora_inclusao']                 = date('H:i');
            $dados['usuario_inclusao']              = TSession::getValue('userid');

            $agendamentoClone->fromArray($dados);
            $agendamentoClone->store();

            if (empty($agendamento->agendamento_anterior)) {
                $agendamento->agendamento_novo = $agendamentoClone->id;
                $agendamento->store();
            }

            TTransaction::close();

            return $agendamentoClone;

        } catch (Exception $e) {
            TTransaction::rollback();
            throw $e;
        }
    }

//Fim Duplicar------------------------------------------------------------------------------------------------
//Fim Duplicar---------------------------------------------------------------------------------------------

//Retorno -----------------------------------------------------------------------------------------------------
    public static function onRetornoCancelar($param = null)
    {
        // Apenas fecha o diálogo sem fazer nada
        return;
    }

    public static function onRetornoAbrirTelaAgendamentoList($param)
    {
        try
        {
            $agendamento_id  = $param['agendamento_id']  ?? null;
            $horario_ini     = $param['horario_inicial'] ?? null;
            $horario_fim     = $param['vhorario_final']  ?? null;
            $paciente_id     = $param['paciente_id']     ?? null;
            $profissional_id = $param['profissional_id'] ?? null;
            $empresa_id      = $param['empresa_id']      ?? null;

            // Validar dados obrigatórios
            if (!$agendamento_id || !$horario_ini) 
            {
                throw new Exception('Dados incompletos para processar o retorno.');
            }

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

            $profissional_pessoa = Pessoa::where('usuario_sistema', '=', $profissional_id)->first();            // Buscar a pessoa pelo campo usuario_sistema = profissional_id

            if (!$profissional_pessoa) 
            {
                TTransaction::close();
                throw new Exception('Profissional não encontrado no cadastro de Pessoa.');
            }

            $dias_retorno = (int)($profissional_pessoa->dias_para_retorno ?? 0);             // Obter dias_para_retorno

            if ($dias_retorno <= 0) 
            {
                TTransaction::close();
                throw new Exception('Prazo para retorno não está configurado para este profissional.');
            }

            $paciente_nome = 'Não informado'; // BUSCAR O NOME DO PACIENTE
            if (!empty($paciente_id)) 
            {
                $paciente = Pessoa::find($paciente_id);
                if ($paciente) 
                {
                    $paciente_nome = $paciente->nome ?? 'Não informado';
                }
            }

            TTransaction::close();

            $dt_inicial = DateTime::createFromFormat('Y-m-d H:i:s', $horario_ini);
            if (!$dt_inicial) 
            {
                $dt_inicial = new DateTime($horario_ini);
            }

            $dt_final = DateTime::createFromFormat('Y-m-d H:i:s', $horario_fim);
            if (!$dt_final) 
            {
                $dt_final = new DateTime($horario_fim);
            }

            // Adicionar os dias para retorno
            $dt_inicial->modify("+{$dias_retorno} days");
            $dt_final->modify("+{$dias_retorno} days");

            // 3. FORMATAR AS DATAS PARA O FILTRO
            $horario_inicial_sugerido = $dt_inicial->format('Y-m-d H:i:s');
            $horario_final_sugerido   = $dt_final->format('Y-m-d H:i:s');

            // 4. GUARDAR FILTROS NA SESSÃO PARA AgendamentoList
            $filtro_dados = array(
                'horario_inicial'      => $horario_inicial_sugerido,
                'vhorario_final'       => $horario_final_sugerido,
                'paciente_id'          => $paciente_id,
                'profissional_id'      => $profissional_id,
                'empresa_id'           => $empresa_id,
                'agendamento_anterior' => $agendamento_id,
                'id'                   => $agendamento_id,
                'modo_retorno'         => 'true',
                'dias_para_retorno'    => $dias_retorno);

            TSession::setValue('filtro_retorno_agendamento', $filtro_dados);

            // 5. ABRIR A LISTAGEM
            AdiantiCoreApplication::loadPage('AgendamentoListRetorno', 'onShow');
        }
        catch (Exception $e)
        {
            TTransaction::rollback();
            new TMessage('error', '<b>' . TSession::getValue('username') . '</b><br>' . $e->getMessage());
        }
    }

    public function onNovoRetorno($param)
    {
        try
        {
            TTransaction::open(self::$database);

            // AGORA SEMPRE CHEGA
            $agendamentoId = $param['agendamento_anterior'] ?? null;

            if (empty($agendamentoId))
            {
                throw new Exception('Agendamento original não informado');
            }

            $agendamentoOriginal = new Agendamento($agendamentoId);

            if (empty($agendamentoOriginal->id))
            {
                throw new Exception('Agendamento original não encontrado');
            }

            $object                         = new stdClass;
            $object->id                     = null;
            $object->agendamento_anterior   = $agendamentoOriginal->id;
            $object->paciente_id            = $agendamentoOriginal->paciente_id;
            $object->empresa_id             = $agendamentoOriginal->empresa_id;
            $object->profissional_id        = $agendamentoOriginal->profissional_id;
            $object->fornecedor_id          = $agendamentoOriginal->fornecedor_id;
            $object->produto_id             = $agendamentoOriginal->produto_id;
            $object->entrega_resultado      = $agendamentoOriginal->entrega_resultado;
            $object->valor_venda            = $agendamentoOriginal->valor_venda;
            $object->valor_taxaentregaexame = $agendamentoOriginal->valor_taxaentregaexame;

            // NOVO HORÁRIO
            $object->horario_inicial  = $param['horario_inicial']  ?? null;
            $object->vhorario_final   = $param['vhorario_final']   ?? null;

            // STATUS
            $object->consulta_retorno = 'S';
            $object->status           = '01';
            $object->cancelado        = 'N';

            // FINANCEIRO
            $object->valor_receber = '0.00';

            $this->form->setData($object);

            TTransaction::close();

            TScript::create("
                setTimeout(function()
                {
                    $('[name=\"valor_receber\"]').val('0.00').trigger('change');
                },300);
            ");
        }
        catch (Exception $e)
        {
            $username = TSession::getValue('username');
            new TMessage('error', "<b>{$username}</b><br>" . $e->getMessage()); 
        }
    }


