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.protocolo_agendamento, t2.cns_paciente) AS identifier_value,
        t1.id_solicitacao,
        t2.cns_paciente,
        t2.cpf_paciente,
        CONCAT(DATE_FORMAT(COALESCE(t4.datahora_cadastro, t1.datahora_agendamento), '%Y-%m-%dT%H:%i:%s'), '-03:00') AS data_registro_criado,
        CONCAT(DATE_FORMAT(COALESCE(t4.datahora_analise, t1.datahora_agendamento), '%Y-%m-%dT%H:%i:%s'), '-03:00') AS data_registro_fim,
        CONCAT(DATE_FORMAT(t1.datahora_agendamento, '%Y-%m-%dT%H:%i:%s'), '-03:00') AS datahora_agendamento,
        "routine" as id_rnds,
        t9.cns_profissional,
        t7.codigo_cbo,
        t8.cnes_estabelecimento,
        '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, 
        CASE
          WHEN t1.status_agendamento = 'A' THEN 'AGENDADO'
          WHEN t1.status_agendamento = 'E' THEN 'AGENDADO'
          WHEN t1.status_agendamento = 'V' THEN 'COMPARECEU'
        END AS status_agendamento
      FROM
        reg_tb_agendamentos 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_tb_solicitacoes t4 ON t4.id_solicitacao = t1.id_solicitacao 
      LEFT JOIN 
        reg_tb_agenda t6 ON t6.id_agenda = t1.id_agenda 
      LEFT JOIN 
        tb_profissional_vinculo t7 ON t7.codigoprofissional_cnes = t6.codigoprofissional_cnes
      LEFT JOIN 
        tb_estabelecimento t8 ON t8.codigoestabelecimento_cnes = t7.codigoestabelecimento_cnes 
      LEFT JOIN 
        (SELECT DISTINCT t7.codigoprofissional_cnes, t7.codigo_cbo
         FROM tb_profissional_vinculo t7
         LEFT JOIN reg_tb_agenda t6 ON t7.codigoprofissional_cnes = t6.codigoprofissional_cnes
         ) AS subquery_t7 ON t7.codigoprofissional_cnes = subquery_t7.codigoprofissional_cnes
      LEFT JOIN 
        tb_profissional t9 ON subquery_t7.codigoprofissional_cnes = t9.codigoprofissional_cnes
      WHERE 
        (t1.status_agendamento = 'A' or t1.status_agendamento = 'E')
        and (t1.enviado_rnds = 'N' or t1.enviado_rnds is null)
        and t1.id_solicitacao is not null
    `;

    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)
      },
      "meta": {
        "lastUpdated": new Date().toISOString()
      },
      "type": "document",
      "timestamp": new Date().toISOString(),
      "entry": [
        {
          "fullUrl": "urn:uuid:transient-0",
          "resource": {
            "resourceType": "Composition",
            "status": "final",
            "title": "Registro de Informações da Regulação Assistencial",
            "meta": {
              "lastUpdated": new Date().toISOString(),
              "profile": [
                "http://www.saude.gov.br/fhir/r4/StructureDefinition/BRRegulacaoAssistencial"
              ]
            },
            "date": new Date().toISOString(),
            "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)
              }
            },
            "author": [
              {
                "identifier": {
                  "system": "http://www.saude.gov.br/fhir/r4/StructureDefinition/BREstabelecimentoSaude-1.0",
                  "value": String(item.cnes_estabelecimento || '6479286')
                }
              }
            ],
            "event": [
              {
                "code": [
                  {
                    "coding": [
                      {
                        "system": "http://www.saude.gov.br/fhir/r4/CodeSystem/BRStatusRegulacaoAssistencial",
                        "code": "booked"
                      }
                    ]
                  }
                ],
                "period": {
                  "start": String(item.datahora_agendamento),
                  "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-1"
                  }
                  
                ]
                
              }
            ],
            
            "section": [
              {
                "entry": [
                  {
                    "reference": "urn:uuid:transient-1"
                  }
                ]
              }
            ]
          }
        },
        {
          "fullUrl": "urn:uuid:transient-1",
          "resource": {
            "resourceType": "Appointment",
            "meta": {
              "lastUpdated": new Date().toISOString(),
              "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",
            "status": "active",
            "meta": {
              "lastUpdated": new Date().toISOString(),
              "profile": [
                "http://www.saude.gov.br/fhir/r4/StructureDefinition/BRRequisicaoRegulacaoAssistencial"
              ]
            },
            "intent": "order",
            "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')
                }
              ]
            },
            "reasonReference": [
              {
                "reference": "urn:uuid:transient-3"
              }
            ]
          }
        },
        {
          "fullUrl": "urn:uuid:transient-3",
          "resource": {
            "resourceType": "Condition",
            "meta": {
              "lastUpdated": new Date().toISOString(),
              "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)
              }
            }
          }
        }
    ]
  }
  };
  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://ehr-services-hmg.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_agendamentos SET enviado_rnds = 'S' WHERE id_solicitacao = ?`,
            [item.id_solicitacao],
            (error) => {
                if (error) {
                    console.error('Erro ao atualizar enviado_rnds:', error.message);
                }
            }
        );

        const successDir = path.join(__dirname, 'responses/successo');
        if (!fs.existsSync(successDir)) {
            fs.mkdirSync(successDir, { recursive: true });
        }

        const successFilePath = path.join(successDir, `S_${item.cns_paciente}_${item.identifier_value}.json`);

        const responseData = {
            data: response.data,
            headers: response.headers
        };

        fs.writeFileSync(successFilePath, JSON.stringify(responseData, null, 2));
        console.log(`Resposta de sucesso salva em: ${successFilePath}`);

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

            const errorDir = path.join(__dirname, 'responses/erros');
            if (!fs.existsSync(errorDir)) {
                fs.mkdirSync(errorDir, { recursive: true });
            }

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

            const errorFilePath = path.join(errorDir, `E_${item.cns_paciente}_${item.identifier_value}.json`);
            fs.writeFileSync(errorFilePath, JSON.stringify(error.response.data, null, 2));
            console.log(`Erro salvo em: ${errorFilePath}`);

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