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 = 'LCMag1302';
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(RPAD(CONCAT(t1.id_solicitacao, t1.numero_procotolo, DATE_FORMAT(NOW(), '%Y%m%d%H%i%S')), 36, '0'), 'P') AS identifier_local,
    t1.id_solicitacao,
    t1.numero_procotolo,
    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,
    CASE
      WHEN (t1.cid_solicitacao IS NULL OR t1.cid_solicitacao = '' OR t1.cid_solicitacao = 'R09') THEN 'R69'
      WHEN (t1.cid_solicitacao IS NULL OR t1.cid_solicitacao = '' OR t1.cid_solicitacao = 'R069') THEN 'R69'
      WHEN (t1.cid_solicitacao = 'ZOO') THEN 'Z00'
      WHEN (((t1.cid_solicitacao <> 'ZOO') AND (t1.cid_solicitacao <> 'R09')) AND (t1.cid_solicitacao IS NOT NULL)) AND (t1.cid_solicitacao <> '') THEN t1.cid_solicitacao
    END AS cid,
    IFNULL(
      CASE
        WHEN REPLACE(t1.observacoes_solicitacao, '<br>', '') = '' THEN 'SEM OBSERVAÇÕES' ELSE UCASE(t1.observacoes_solicitacao)
      END,
      'SEM OBSERVAÇÕES'
    ) AS observacao_agendamento,
    t3.codigo_sus,
    CASE
      WHEN ((((
        (t1.codigoprofissional_cnes IS NULL) OR (t1.codigoprofissional_cnes = ''))
        OR (t1.codigoprofissional_cnes = '2919200000000000'))
        OR (t1.codigoprofissional_cnes = '2919200000000001'))
        OR (t1.codigoprofissional_cnes = '2919200000000002'))
        OR (t1.codigoprofissional_cnes = '2919200000000003')
      THEN
        '225133'
      ELSE
        tb_profissional_vinculo.codigo_cbo
    END AS codigo_cbo,
    CASE
      WHEN ((((
        (t1.codigoprofissional_cnes IS NULL) OR (t1.codigoprofissional_cnes = ''))
        OR (t1.codigoprofissional_cnes = '2919200000000000'))
        OR (t1.codigoprofissional_cnes = '2919200000000001'))
        OR (t1.codigoprofissional_cnes = '2919200000000002'))
        OR (t1.codigoprofissional_cnes = '2919200000000003')
      THEN
        '6479286'
      ELSE
        RIGHT(tb_profissional_vinculo.codigoestabelecimento_cnes, 7)
    END 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 = '4' THEN 'PENDENTE'
    END AS status_agendamento_2
    FROM
      tb_paciente t2
      LEFT OUTER JOIN reg_tb_solicitacoes t1 ON (t2.id_paciente = t1.id_paciente)
      RIGHT OUTER JOIN reg_tb_procedimento t3 ON (t3.id_procedimento = t1.id_procedimento)
      RIGHT OUTER JOIN reg_rl_statussolicitacao t4 ON (t4.id_statussolicitacao = t1.id_statussolicitacao)
      RIGHT OUTER JOIN reg_rl_classificacaorisco t5 ON (t5.id_classificacaorisco = t1.id_classificacaorisco)
      RIGHT OUTER JOIN tb_estabelecimento tb_estabelecimento ON (tb_estabelecimento.codigoestabelecimento_cnes = t1.id_unidade_cadastrou)
      LEFT OUTER JOIN tb_profissional_vinculo tb_profissional_vinculo ON (tb_estabelecimento.codigoestabelecimento_cnes = tb_profissional_vinculo.codigoestabelecimento_cnes)
    WHERE
      (t1.id_statussolicitacao = '2')
      AND (t1.enviado_rnds_pendente = 'N' OR t1.enviado_rnds_pendente IS NULL)
      AND (t1.id_grupo_procedimento='14')
      AND (observacoes_solicitacao != 'REGISTRO MIGRADO DO SISREG')
      AND (date_format(t1.datahora_cadastro,'%Y-%m-%d')>='2024-01-01')
    GROUP BY
    t3.codigo_sus,
    CASE
      WHEN ((((
        (t1.codigoprofissional_cnes IS NULL) OR (t1.codigoprofissional_cnes = ''))
        OR (t1.codigoprofissional_cnes = '2919200000000000'))
        OR (t1.codigoprofissional_cnes = '2919200000000001'))
        OR (t1.codigoprofissional_cnes = '2919200000000002'))
        OR (t1.codigoprofissional_cnes = '2919200000000003')
      THEN
        '6479286'
      ELSE
        RIGHT(tb_profissional_vinculo.codigoestabelecimento_cnes, 7)
    END,
    t1.id_solicitacao, 
    t1.numero_procotolo, 
    CONCAT(t1.id_solicitacao,t1.numero_procotolo, DATE_FORMAT(NOW(), '%Y%m%d%H%i%S'),'P')
    ORDER BY date_format(t1.datahora_cadastro,'%Y%m%d%H%i%S') ASC
    LIMIT 500`

    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_local)
    },
    "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": {
                "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": "routine",
          "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 || '225125')
              }
            ]
          },
          "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"
            ]
          },
          "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('700506440995960')
        },
        httpsAgent: httpsAgent
      }
    );
    console.log('SUCESSO:', response.data);
    quantidadeEnviada++;

    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/', '');
    }

    connection.query(
      `UPDATE reg_tb_solicitacoes SET enviado_rnds_pendente='S', identifier_enviornds_pendente=?, id_retornornds_pendente=? WHERE id_solicitacao = ?`,
      [item.identifier_local, extractedLocation, 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, [extractedLocation, item.numero_procotolo + ' | ' + item.identifier_local], (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', identifier_enviornds_pendente=?, id_retornornds_pendente=? WHERE id_solicitacao = ?`,
          [item.identifier_local, extractedDiagnostics, 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 + ' | ' + item.identifier_local], (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_procotolo + ' | ' + item.identifier_local], (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();
