const fs = require('fs');
const path = require('path');
const mysql = require('mysql2');
const axios = require('axios');
const https = require('https');
const dotenv = require('dotenv');
const envData = fs.readFileSync('conecta.env', 'utf8');
const envVariables = dotenv.parse(envData);
dotenv.config();

const certFilePath = path.join(__dirname, 'certificado.pem');
const keyFilePath = path.join(__dirname, 'chave.pem');
const passphrase = '130203';
const tokenFilePath = path.join(__dirname, 'token.txt');

let quantidadeEnviada = 0;
let quantidadeErro = 0;
const {
  DB_MYSQL_SERVER,
  DB_MYSQL_USERNAME,
  DB_MYSQL_PASSWORD,
  DB_MYSQL_NAME,
} = envVariables;

function getToken() {
    try {
        const data = fs.readFileSync(tokenFilePath, 'utf8');
        const match = data.match(/TOKEN:\s*(.+)/);
        if (match && match[1]) {
            return match[1].trim();
        } else {
            throw new Error('Token não encontrado no arquivo.');
        }
    } catch (err) {
        console.error('Erro ao ler o token:', err.message);
        return null;
    }
}

const connection = mysql.createConnection({
  host: DB_MYSQL_SERVER,
  user: DB_MYSQL_USERNAME,
  password: DB_MYSQL_PASSWORD,
  database: DB_MYSQL_NAME,
});

function fetchData() {
  return new Promise((resolve, reject) => {
    const query = `
    
    SELECT  
        CONCAT(t1.id_solicitacao, t1.numero_procotolo, t1.id_paciente, t1.numero_procotolo) AS identifier_value,
		t1.numero_procotolo,
       	t1.id_solicitacao,
		t2.cns_paciente,
        t2.cpf_paciente,
        CONCAT(
        DATE_FORMAT(
            COALESCE(t1.datahora_cadastro, NOW()), 
            '%Y-%m-%dT%H:%i:%s'
        ), 
        '-03:00'
    ) AS data_registro_criado,
    CONCAT(
        DATE_FORMAT(
            CASE
                WHEN COALESCE(t1.datahora_analise, t1.datahora_cadastro, NOW()) <= COALESCE(t1.datahora_cadastro, NOW())
                THEN DATE_ADD(COALESCE(t1.datahora_cadastro, NOW()), INTERVAL 1 HOUR) 
                ELSE COALESCE(t1.datahora_analise, t1.datahora_cadastro, NOW())
            END, 
            '%Y-%m-%dT%H:%i:%s'
        ), 
        '-03:00'
    ) AS data_registro_fim,
        t5.id_rnds,
        'R69' as CID,
                    IFNULL(
                CASE 
                    WHEN REPLACE(t1.observacao_agendamento, '<br>', '') = '' THEN 'Sem observações'
                    ELSE t1.observacao_agendamento
                END, 
                'Sem observações'
            ) AS observacao_agendamento,
            t3.codigo_sus, 
             "700000269125609" AS cns_profissional,
             "223505" AS codigo_cbo,
             "6479286" AS cnes_estabelecimento,
            t4.nome_statusslicitacao as status_agendamento,
        CASE
            WHEN t1.id_statussolicitacao = '1' THEN 'PENDENTE'
            WHEN t1.id_statussolicitacao = '2' THEN 'PENDENTE'
            WHEN t1.id_statussolicitacao = '3' THEN 'AGENDADO'
            WHEN t1.id_statussolicitacao = '4' THEN 'PENDENTE'
            WHEN t1.id_statussolicitacao = '5' THEN 'CANCELADO'
            WHEN t1.id_statussolicitacao = '6' THEN 'AGENDADO'
            WHEN t1.id_statussolicitacao = '7' THEN 'AGENDADO'
            WHEN t1.id_statussolicitacao = '8' THEN 'COMPARECEU'
            WHEN t1.id_statussolicitacao = '9' THEN 'CANCELADO'
            WHEN t1.id_statussolicitacao = '10' THEN 'CANCELADO'
        END AS status_agendamento_2
 FROM
    reg_tb_solicitacoes t1
LEFT JOIN 
    tb_paciente t2 ON t2.id_paciente = t1.id_paciente 
LEFT JOIN 
    reg_tb_procedimento t3 ON t3.id_procedimento = t1.id_procedimento 
    LEFT JOIN 
    reg_rl_statussolicitacao t4 ON t4.id_statussolicitacao= t1.id_statussolicitacao 
LEFT JOIN 
    reg_rl_classificacaorisco t5 ON t5.id_classificacaorisco = t1.id_classificacaorisco 
    where
      (t1.id_statussolicitacao = '1' or t1.id_statussolicitacao = '2' or t1.id_statussolicitacao = '4')
	   and (t1.enviado_rnds_pendente = 'N' or t1.enviado_rnds_pendente is null)
	   limit 50  
    `;

    connection.query(query, (error, results) => {
      if (error) {
        reject(error);
      } else {
        resolve(results);
      }
    });
  });
}

// BUNDLE
function buildBundle(item) {
  return {
		"resourceType": "Bundle",
		"identifier": {
			"system": "http://www.saude.gov.br/fhir/r4/NamingSystem/BRRNDS-41484",
			"value": String(item.identifier_value)
		},
		"type": "document",
		"timestamp": new Date().toISOString(),
		"entry": [
			{
				"fullUrl": "urn:uuid:transient-0",
				"resource": {
					"resourceType": "Composition",
					"meta": {
						"profile": [
							"http://www.saude.gov.br/fhir/r4/StructureDefinition/BRRegulacaoAssistencial"
						]
					},
					"status": "final",
					"type": {
						"coding": [
							{
								"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRTipoDocumento",
								"code": "RA"
							}
						]
					},
					"category": [
						{
							"coding": [
								{
									"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRModalidadeAssistencial",
									"code": "09"
								}
							]
						}
					],
					"subject": {
						"identifier": {
							"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BRIndividuo-1.0",
							"value": String(item.cpf_paciente|| item.cns_paciente)
						}
					},
					"date": String(item.data_registro_fim),
					"author": [
						{
							"identifier": {
								"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BREstabelecimentoSaude-1.0",
								"value": String(item.cnes_estabelecimento || '6479286')
							}
						}
					],
					"title": "Registro de Informações da Regulação Assistencial",
					"event": [
						{
							"code": [
								{
									"coding": [
										{
											"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRStatusRegulacaoAssistencial",
											"code": "pending"
										}
									]
								}
							],
							"period": {
							"start":String(item.data_registro_criado),
							"end": String(item.data_registro_fim)
							},
							"detail": [
								{
									"identifier": {
										"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BREstabelecimentoSaude-1.0",
									"value": String(item.cnes_estabelecimento || '6479286')
									}
								},
								{
									"reference": "urn:uuid:transient-2"
								}
							]
						}
					],
					"section": [
						{
							"entry": [
								{
									"reference": "urn:uuid:transient-1"
								}
							]
						}
					]
				}
			},
			{
				"fullUrl": "urn:uuid:transient-1",
				"resource": {
					"resourceType": "Appointment",
					"meta": {
						"profile": [
							"http://www.saude.gov.br/fhir/r4/StructureDefinition/BRAgendamentoRegulacaoAssistencial"
						]
					},
					"status": "booked",
					"serviceCategory": [
						{
							"coding": [
								{
									"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRModalidadeAssistencial",
									"code": "09"
								}
							]
						}
					],
					"serviceType": [
						{
							"coding": [
								{
									"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRTabelaSUS",
									"code": String(item.codigo_sus)
								}
							]
						}
					],
					"specialty": [
						{
							"coding": [
								{
									"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO",
									"code": String(item.codigo_cbo || '225133')
								}
							]
						}
					],
					"appointmentType": {
						"coding": [
							{
								"system": "http://hl7.org/fhir/request-priority",
								"code": String(item.id_rnds)
							}
						]
					},
					"reasonReference": [
						{
							"reference": "urn:uuid:transient-3"
						}
					],
					"start": String(item.data_registro_criado),
					"end": String(item.data_registro_fim),
					"created": String(item.data_registro_criado),
					"basedOn": [
						{
							"reference": "urn:uuid:transient-2"
						}
					],
					"participant": [
						{
							"type": [
								{
									"coding": [
										{
											"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRTipoParticipante",
											"code": "PCT"
										}
									]
								}
							],
							"actor": {
								"identifier": {
									"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BRIndividuo-1.0",
									"value": String(item.cpf_paciente|| item.cns_paciente)
								}
							},
							"status": "accepted"
						}
					]
				}
			},
			{
				"fullUrl": "urn:uuid:transient-2",
				"resource": {
					"resourceType": "ServiceRequest",
					"meta": {
						"profile": [
							"http://www.saude.gov.br/fhir/r4/StructureDefinition/BRRequisicaoRegulacaoAssistencial"
						]
					},
					"status": "active",
					"intent": "proposal",
					"category": [
						{
							"coding": [
								{
									"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRModalidadeAssistencial",
									"code": "09"
								}
							]
						}
					],
					"priority": String(item.id_rnds),
					"code": {
						"coding": [
							{
								"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRTabelaSUS",
								"code": String(item.codigo_sus)
							}
						]
					},
					"subject": {
						"identifier": {
							"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BRIndividuo-1.0",
							"value": String(item.cpf_paciente|| item.cns_paciente)
						}
					},
					"authoredOn": String(item.data_registro_criado),
					"requester": {
						"identifier": {
							"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BREstabelecimentoSaude-1.0",
						"value": String(item.cnes_estabelecimento || '6479286')
						}
					},
					"performerType": {
						"coding": [
							{
								"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCBO",
								"code": String(item.codigo_cbo || '225133')
							}
						]
					},
					"performer": [
						{
							"identifier": {
								"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BREstabelecimentoSaude-1.0",
								"value": String(item.cnes_estabelecimento || '6479286')
							}
						}
					],
					"reasonReference": [
						{
							"reference": "urn:uuid:transient-3"
						}
					]
				}
			},
			{
				"fullUrl": "urn:uuid:transient-3",
				"resource": {
					"resourceType": "Condition",
					"meta": {
						"profile": [
							"http://www.saude.gov.br/fhir/r4/StructureDefinition/BRCID10Avaliado-1.0"
						]
					},
					"clinicalStatus": {
						"coding": [
							{
								"system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
								"code": "active"
							}
						]
					},
					"category": [
						{
							"coding": [
								{
									"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCategoriaDiagnostico",
									"code": "01",
									"display": "Principal"
								}
							]
						}
					],
					"code": {
						"coding": [
							{
								"system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRCID10",
								"code": String(item.CID)
							}
						]
					},
					"subject": {
						"identifier": {
							"system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BRIndividuo-1.0",
							"value": String(item.cpf_paciente|| item.cns_paciente)
						}
					},
					"note": [
						{
							"text": String(item.observacao_agendamento)
						}
					]
				}
			}
		]
   }
};
  async function sendBundle(item) {
    const token = getToken();
    if (!token) {
        console.error('Token não disponível. Não é possível enviar o bundle.');
        return;
    }

    try {
        const httpsAgent = new https.Agent({
            cert: fs.readFileSync(certFilePath),
            key: fs.readFileSync(keyFilePath),
            passphrase: passphrase,
            rejectUnauthorized: true
        });

        const response = await axios.post(
            'https://ba-ehr-services.saude.gov.br/api/fhir/r4/Bundle',
            buildBundle(item),
            {
                headers: {
                    'Content-Type': 'application/json',
                    'X-Authorization-Server': `Bearer ${token}`,
                    'Authorization': String(item.cns_profissional || '702708666176460')
                },
                httpsAgent: httpsAgent
            }
        );
		console.log('SUCESSO:', response.data);
        quantidadeEnviada++;
        
      
        connection.query(
            `UPDATE reg_tb_solicitacoes SET enviado_rnds_pendente = 'S' WHERE id_solicitacao = ?`,
            [item.id_solicitacao],
            (error) => {
                if (error) {
                    console.error('Erro ao atualizar enviado_rnds_pendente:', error.message);
                }
            }
        );


		const locationHeader = response.headers.location || null;
		let extractedLocation = null;
		
		if (locationHeader) {
		
			extractedLocation = locationHeader.replace('https://ba-ehr-services.saude.gov.br/1.15/api/fhir/r4/Bundle/', '');
		}
		
		const queryInsertSuccess = `
            INSERT INTO reg_tb_enviornds (json_retornosucesso, tipo_envio, protocolo_envio)
            VALUES (?, 'PENDENTE', ?)
        `;
        
        connection.query(queryInsertSuccess, [extractedLocation, item.numero_procotolo], (error) => {
            if (error) {
                console.error('Erro ao inserir no reg_tb_enviornds (sucesso):', error.message);
            } else {
                console.log('Resposta de sucesso salva no banco.');
            }
        });
	} catch (error) {
        if (error.response) {
            const diagnosticsData = (error.response.data.issue && error.response.data.issue.length > 0)
                ? error.response.data.issue[0].diagnostics
                : null;

            let extractedDiagnostics = null;
            if (diagnosticsData) {
                extractedDiagnostics = diagnosticsData; 
            }

            if (diagnosticsData && diagnosticsData.includes('EDS-MSG010')) {
                console.log('Identifier duplicado:', diagnosticsData);
                quantidadeEnviada++; 

                connection.query(
                    `UPDATE reg_tb_solicitacoes SET enviado_rnds_pendente = 'S' WHERE id_solicitacao = ?`,
                    [item.id_solicitacao],
                    (error) => {
                        if (error) {
                            console.error('Erro ao atualizar enviado_rnds_pendente:', error.message);
                        }
                    }
                );

                const queryInsertSuccess = `
                    INSERT INTO reg_tb_enviornds (json_retornosucesso, tipo_envio, protocolo_envio)
                    VALUES (?, 'PENDENTE', ?)
                `;
                connection.query(queryInsertSuccess, [extractedDiagnostics, item.numero_procotolo], (error) => {
                    if (error) {
                        console.error('Erro ao inserir no reg_tb_enviornds (sucesso):', error.message);
                    } else {
                        console.log('Resposta de sucesso salva no banco.');
                    }
                });

            } else {
                quantidadeErro++;
                console.error('Request failed:', error.response.status);
                console.error('Response:', error.response.data);

                connection.query(
                    `UPDATE reg_tb_solicitacoes SET enviado_rnds_pendente = 'N' WHERE id_solicitacao = ?`,
                    [item.id_solicitacao],
                    (error) => {
                        if (error) {
                            console.error('Erro ao atualizar enviado_rnds_pendente:', error.message);
                        }
                    }
                );

                const queryInsertError = `
                    INSERT INTO reg_tb_enviornds (json_retornoerro, tipo_envio, protocolo_envio)
                    VALUES (?, 'PENDENTE', ?)
                `;
                connection.query(queryInsertError, [extractedDiagnostics, item.numero_protocolo], (dbError) => {
                    if (dbError) {
                        console.error('Erro ao inserir no reg_tb_enviornds (erro):', dbError.message);
                    } else {
                        console.log('Resposta de erro salva no banco.');
                    }
                });
            }

        } else {
            console.error('Request failed:', error.message);
        }
    }
}

async function process() {

    try {
        const data = await fetchData();
        for (const item of data) {
            await sendBundle(item);
        }

        const queryInsert = `
            INSERT INTO reg_tb_enviado_rnds (tipo_envio, data_envio, quantidade_enviada, quantidade_erro)
            VALUES ('PENDENTE', NOW(), ?, ?)
        `;
        connection.query(queryInsert, [quantidadeEnviada, quantidadeErro], (error) => {
            if (error) {
                console.error('Erro ao inserir na tabela reg_tb_enviado_rnds:', error.message);
            } else {
                console.log('Consolidação de envios inserida com sucesso.');
            }
        });

    } catch (err) {
        console.error('Erro ao processar dados:', err.message);
    } finally {
        connection.end();
    }
}

process();
