const server_constants = require('../tools/server_constants');

const shared_consts = require('../tools/shared_nodejs');

const tools = require('../tools/general');

const axios = require('axios');

const T_Web_Articoli = require('../models/t_web_articoli');
const T_Web_Argomenti = require('../models/t_web_argomenti');
const T_Web_StatiProdotto = require('../models/t_web_statiprodotto');
const T_Web_TipiFormato = require('../models/t_web_tipiformato');

const SERVER_A_URL = process.env.SERVER_A_URL || '';
const API_KEY = process.env.API_KEY_MSSQL;

const mongoose = require('mongoose').set('debug', false);

// Funzione per ottenere i dati
const getArticlesSales = async () => {
  try {
    const query = `
            SELECT 
                a.IdArticolo, a.Titolo, a.DataPubblicazione, a.Ean13 AS isbn, 
                a.IdCollana, y.DescrizioneCollana, i2.DescrArgomento, a.ListaArgomenti, 
                a.Pagine, a.IdTipoFormato, a.Misure, 
                COALESCE(o.totVen, 0) as totVen, COALESCE(u.totFat, 0) as totFat, 
                COALESCE(p.rank3M, 0) as rank3M, COALESCE(t.fatrank3M, 0) as fatrank3M,
                COALESCE(q.rank6M, 0) as rank6M, COALESCE(r.rank1Y, 0) as rank1Y,
                COALESCE(t.fat3mesi, 0) as fatLast3M,
                COALESCE(t2.fat6mesi, 0) as fatLast6M,
                COALESCE(p.venduti3mesi, 0) as vLast3M,
                COALESCE(q.venduti6mesi, 0) as vLast6M, COALESCE(r.venduti1anno, 0) as vLast1Y,
                s.ultimoOrdine as dataUltimoOrdine
            FROM T_WEB_Articoli a
            LEFT JOIN (SELECT CodArticoloGM, SUM(Qta) as totVen FROM T_WEB_Ordini GROUP BY CodArticoloGM) o 
                ON a.IdArticolo = o.CodArticoloGM
            LEFT JOIN (SELECT CodArticolo, SUM(TRY_CAST(Qta AS INT)) as totFat FROM T_WEB_ArticoliFatturati WHERE ISNUMERIC(Qta) = 1 GROUP BY CodArticolo) u 
                ON a.IdArticolo = u.CodArticolo
            WHERE a.IdStatoProdotto IS NOT NULL
            ORDER BY totVen DESC;
        `;

    const response = await axios.post(
      SERVER_A_URL + '/query',
      { query },
      {
        headers: { 'x-api-key': API_KEY },
      }
    );

    return response.data || [];
  } catch (error) {
    console.error('Errore nel recupero degli articoli:', error);
    throw new Error('Errore nel recupero degli articoli venduti.');
  }
};

// Endpoint per ottenere i dati in formato JSON
exports.getArticlesSalesHandler = async (req, res) => {
  try {
    const data = await getArticlesSales();
    if (!data.length) return res.status(404).json({ message: 'Nessun articolo trovato.' });
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

// Endpoint per esportare i dati come file JSON
exports.exportArticlesSalesByJSON = async (req, res) => {
  try {
    const data = await getArticlesSales();
    if (!data.length) return res.status(404).json({ message: 'Nessun articolo trovato.' });

    res.setHeader('Content-Type', 'application/json');
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="ranking_articles_${new Date().toISOString().split('T')[0]}.json"`
    );
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

exports.getTableContent = async (options) => {
  try {
    // Chiama getTableContent, se ritorna errore hangup, allora attendi 2 secondi e poi richiamala.
    const tableContent = await this.getTableContentBase(options);
    console.log('   uscito dalla funzione getTableContentBase ... ');
    return tableContent;
  } catch (error) {
    console.error('Error: ', error?.message);
    if (error.message === 'socket hang up') {
      console.log('Error: hangup, waiting 2 seconds and retrying...');
      await new Promise((resolve) => setTimeout(resolve, 2000));
      return await this.getTableContent(options);
    }
  }
};

exports.formatDate = (dateValue) => {
  const date = new Date(dateValue);
  const day = String(date.getDate()).padStart(2, '0');
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const year = date.getFullYear();
  return `${day}/${month}/${year}`;
};

exports.getModelByNameTable = (nameTable) => {
  switch (nameTable) {
    case 'T_Web_Articoli':
      return T_Web_Articoli;
    case 'T_Web_StatiProdotto':
      return T_Web_StatiProdotto;
    case 'T_Web_TipiFormato':
      return T_Web_TipiFormato;
    default:
      return null;
  }
};

exports.getTableContentBase = async (options) => {
  try {
    const myurl = SERVER_A_URL + '/query';
    console.log('getTableContentBase...', myurl);
    // Verifica se la tabella esiste
    const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`;
    const checkResponse = await axios.post(
      myurl,
      { query: checkTableQuery },
      {
        headers: { 'x-api-key': API_KEY },
      }
    );
    console.log('   risposta 1...');
    if (!checkResponse?.data || checkResponse?.data.length === 0 || checkResponse?.data[0].tableExists === 0) {
      return `La tabella '${options.nameTable}' non esiste.`;
    }

    // Recupera le colonne della tabella principale dal catalogo
    const columnsQuery = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '${options.nameTable}'`;
    const columnsResponse = await axios.post(
      SERVER_A_URL + '/query',
      { query: columnsQuery },
      {
        headers: { 'x-api-key': API_KEY },
      }
    );
    console.log('   risposta 2 (schema)...');
    const tableColumns = columnsResponse.data.map((col) => col.COLUMN_NAME);

    // Mappatura per unire i campi (ID e Descrizione)
    const mergedMapping = {
      IdStatoProdotto: 'DescrizioneStatoProdotto',
      IdTipologia: 'DescrizioneTipologia',
      IdTipoFormato: 'DescrizioneFormato',
      IdCollana: 'DescrizioneCollana',
      ListaArgomenti: 'DescrArgomento',
      ListaAutori: 'AutoriCompleti',
      IdMarchioEditoriale: 'CasaEditrice',
    };

    // Costruisce la query per recuperare i record
    let dataQuery = '';

    let records = [];

    if (options?.usaDBGMLocale) {
      // Cerca il modello corrispondente alla tabella se esiste
      let mymodel = this.getModelByNameTable(options.nameTable);
      if (!mymodel) {
        // fai una query sul db locale mongodb dela tabella chiamata "options.nameTable"
        mymodel = mongoose.model(options.nameTable, new mongoose.Schema({}, { strict: false }));
        if (!mymodel) return `Il modello per la tabella '${options.nameTable}' non esiste.`;
      }

      if (options.aggregation) {
        console.log('options.aggregation', options.aggregation);
        records = await mymodel.aggregate(options.aggregation);
      } else {
        const pipeline = [];

        // Filtro base se specificato
        if (options.where) {
          const whereConditions = options.where;
          pipeline.push({ $match: whereConditions });
        }

        if (options.sort) {
          pipeline.push({ $sort: options.sort });
        }

        if (options.limit) {
          pipeline.push({ $limit: options.limit });
        }

        // Selezione dei campi
        if (options.fieldGM) {
          pipeline.push({ $project: { [options.fieldGM]: 1 } });
        }

        console.log('   aggregate pipeline...', pipeline);
        records = await mymodel.aggregate(pipeline);
      }

      console.log('results', records ? records[0] : ' non ricevuto');
    } else {
      let columnsToShow = 'T.*';
      if (options.fieldGM) {
        columnsToShow = 'T.' + options.fieldGM;
      }

      if (options.nameTable.toLowerCase() === 't_web_articoli') {
        if (true) {
          dataQuery =
            `
            SELECT TOP ${options.numrec || 10000}
            ${columnsToShow}
            ` +
            (options.campispeciali
              ? `
            ,i.DescrizioneTipologia
            ,f.DescrizioneStatoProdotto
            ,n.DescrizioneFormato
            ,y.DescrizioneCollana
            ,z.AutoriCompleti
            ,i2.DescrArgomento
            ,z3.CasaEditrice`
              : ``) +
            (options.showQtaDisponibile ? ` ,q.QtaDisponibile ` : ``) +
            ` FROM T_WEB_Articoli T WITH (noLock)
                RIGHT JOIN(
                    SELECT IdArticolo, MAX(DataOra) AS data 
            FROM T_WEB_Articoli 
            GROUP BY IdArticolo
                ) b ON T.IdArticolo = b.IdArticolo AND T.DataOra = b.data ` +
            (options.campispeciali
              ? `               
            RIGHT JOIN
        (     SELECT
                        e.IdStatoProdotto,
                        e.Descrizione as DescrizioneStatoProdotto
                FROM
                        T_WEB_StatiProdotto e
                JOIN
                        (
                                SELECT
                                        IdStatoProdotto,
                                        MAX(DataOra) as data1
                                FROM
                                        T_WEB_StatiProdotto
                                GROUP BY
                                        IdStatoProdotto ) c
                ON
                        e.IdStatoProdotto = c.IdStatoProdotto
                AND     e.DataOra         = c.data1 ) f
ON
        T.IdStatoProdotto = f.IdStatoProdotto

        RIGHT JOIN(
                        SELECT g.IdTipologia,
                        g.Descrizione as DescrizioneTipologia
            FROM
            T_WEB_Tipologie g
            JOIN(
                            SELECT IdTipologia, MAX(DataOra) as data1
                FROM
                T_WEB_Tipologie
                GROUP BY IdTipologia
                        ) h ON g.IdTipologia = h.IdTipologia AND g.DataOra = h.data1
                    ) i ON
                    T.IdTipologia = i.IdTipologia
        RIGHT JOIN(
                        SELECT l.IdTipoFormato,
                        l.Descrizione as DescrizioneFormato
            FROM T_WEB_TipiFormato l
            JOIN(
                            SELECT IdTipoFormato, MAX(DataOra) as data1
                FROM T_WEB_TipiFormato
                GROUP BY IdTipoFormato
                        ) m ON l.IdTipoFormato = m.IdTipoFormato AND l.DataOra = m.data1
                    ) n ON T.IdTipoFormato = n.IdTipoFormato
        RIGHT JOIN(
                        SELECT v.IdCollana,
                        v.Descrizione as DescrizioneCollana
            FROM T_WEB_Collane v
            INNER JOIN(
                            SELECT IdCollana,
                            MAX(ID) as MaxID
                FROM T_WEB_Collane
                GROUP BY IdCollana
                        ) x ON v.IdCollana = x.IdCollana AND v.ID = x.MaxID
                    ) y ON T.IdCollana = y.IdCollana        
        RIGHT JOIN(
                        SELECT g2.IdArgomento, g2.Descrizione as DescrArgomento
            FROM T_WEB_Argomenti g2
            INNER JOIN(
                            SELECT IdArgomento, MAX(DataOra) as data12
                FROM T_WEB_Argomenti
                GROUP BY IdArgomento
                        ) h ON g2.IdArgomento = h.IdArgomento AND g2.DataOra = h.data12
                    ) i2 ON T.ListaArgomenti = i2.IdArgomento
                    ` +
                (options.showQtaDisponibile
                  ? ` RIGHT JOIN(
                                SELECT o.Codice, o.QtaDisponibile
                        FROM T_WEB_Disponibile o
                        JOIN(
                                    SELECT Codice, MAX(DataOra) as data1
                            FROM T_WEB_Disponibile
                            GROUP BY Codice
                                ) p ON o.Codice = p.Codice AND o.DataOra = p.data1
                            ) q ON T.IdArticolo = q.Codice`
                  : ``) +
                `   RIGHT JOIN(
                      SELECT a3.IdMarchioEditoriale, a3.Descrizione as CasaEditrice
      FROM T_WEB_MarchiEditoriali a3
      JOIN(
                          SELECT IdMarchioEditoriale, MAX(DataOra) as maxData
           FROM T_WEB_MarchiEditoriali
           GROUP BY IdMarchioEditoriale
                      ) aa3 ON a3.IdMarchioEditoriale = aa3.IdMarchioEditoriale AND a3.DataOra = aa3.maxData
                  ) z3 ON T.IdMarchioEditoriale = z3.IdMarchioEditoriale  

RIGHT JOIN(
                        SELECT 
                T1.IdArticolo,
                        STUFF((
                            SELECT ',' + ISNULL(A2.AutoreCompleto, '')
                    FROM(
                                SELECT CAST('<root><x>' + REPLACE(T1.ListaAutori, ',', '</x><x>') + '</x></root>' AS XML) AS DataXML
                            ) X
                    CROSS APPLY X.DataXML.nodes('/root/x') AS A(x)
                    CROSS APPLY(
                                SELECT TRY_CAST(LTRIM(RTRIM(A.x.value('.', 'VARCHAR(100)'))) AS INT) AS AutoreID
                            ) CA
                    JOIN(
                                SELECT a.IdAutore, CONCAT(a.Nome, ' ', a.Cognome) AS AutoreCompleto
                        FROM T_WEB_Autori a
                        RIGHT JOIN(
                                    SELECT IdAutore, MAX(DataOra) AS maxData
                            FROM T_WEB_Autori
                            GROUP BY IdAutore
                                ) aa ON a.IdAutore = aa.IdAutore AND a.DataOra = aa.maxData
                            ) A2 ON CA.AutoreID = A2.IdAutore
                    FOR XML PATH(''), TYPE
                        ).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS AutoriCompleti
                        FROM T_WEB_Articoli T1
                        WHERE t1.DataOra = (select max(DataOra) AS DataOra from T_web_articoli As h WHERE h.IdArticolo = T1.IdArticolo)
           
                        GROUP BY T1.IdArticolo, T1.ListaAutori ) z ON T.IdArticolo = z.IdArticolo                        
`
              : ``);
        } else {
          dataQuery += `
                SELECT TOP ${options.numrec}
                T.*
                    FROM T_WEB_Articoli T
                JOIN(
                    SELECT IdArticolo, MAX(DataOra) AS data 
                                    FROM T_WEB_Articoli 
                                    GROUP BY IdArticolo
                ) b ON T.IdArticolo = b.IdArticolo AND T.DataOra = b.data
                    `;
        }
      } else {
        dataQuery = `SELECT TOP ${options.numrec || 10000} * FROM ${options.nameTable} `;
      }
      if (options.where && options.where.trim() !== '') {
        dataQuery += ` WHERE ${options.where} `;
      }

      console.log('dataQuery', dataQuery);

      // Esegue la query per recuperare i dati
      // console.log('dataQuery', dataQuery);
      const dataResponse = await axios.post(
        SERVER_A_URL + '/query',
        { query: dataQuery },
        {
          headers: { 'x-api-key': API_KEY },
        }
      );

      records = dataResponse?.data;
    }

    if (!records || records.length === 0) {
      console.log(`Nessun record trovato per la tabella ${options.nameTable}.`);
      return [];
    }

    // Determina quali colonne visualizzare.
    let displayColumns;
    if (options.nameTable.toLowerCase() === 't_web_articoli') {
      // Usa tutte le proprietà del record, escludendo le colonne dei campi uniti (quelle usate per il merge)
      displayColumns = Object.keys(records[0]).filter((col) => !Object.values(mergedMapping).includes(col));
    } else {
      displayColumns = tableColumns;
    }

    // Funzione per ottenere il valore da visualizzare, fondendo i campi se presente nella mappatura
    const getDisplayValue = (record, col) => {
      let value = record[col] ?? 'NULL';
      // Format date solo se il nome della colonna indica una data/ora
      if ((col.toLowerCase().includes('data') || col.toLowerCase().includes('ora')) && value !== 'NULL') {
        if (value.includes(',')) {
          // Se ci sono più valori separati da virgola, formatta ciascuno se è una data valida
          value = value
            .split(',')
            .map((item) => {
              const trimmed = item.trim();
              const parsed = Date.parse(trimmed);
              return !isNaN(parsed) ? this.formatDate(trimmed) : trimmed;
            })
            .join(', ');
        } else {
          const parsed = Date.parse(value);
          if (!isNaN(parsed)) {
            value = this.formatDate(value);
          }
        }
      }
      if (mergedMapping[col]) {
        return `${record[mergedMapping[col]] || ''} (${value})`;
      }
      return value;
    };

    // Costruisce l'output HTML
    let output = '';
    if (options.outhtml) {
      if (records.length === 1) {
        // Se c'è un solo record, visualizza una lista di chiavi e valori
        const record = records[0];
        output += `
                    <table border='1' style="border-collapse: collapse;" >
                  <thead>
                    <tr>
                      <th style="padding: 8px; background-color: #f2f2f2;">Campo</th>
                      <th style="padding: 8px; background-color: #f2f2f2;">Valore</th>
                    </tr>
                  </thead>
                  <tbody>
            `;
        displayColumns.forEach((column) => {
          output += `
                    <tr>
                      <td style="padding: 8px;">${column}</td>
                      <td style="padding: 8px;">${getDisplayValue(record, column)}</td>
                    </tr>
                `;
        });
        output += `
                  </tbody>
                </table>
    `;
      } else {
        // Se ci sono più record, visualizza una tabella con intestazioni
        output += "<table border='1' style='border-collapse: collapse; width: 100%;'><thead><tr>";
        displayColumns.forEach((column) => {
          output += `< th style = "padding: 8px; background-color: #f2f2f2;" > ${column}</th > `;
        });
        output += '</tr></thead><tbody>';
        records.forEach((record) => {
          output += '<tr>';
          displayColumns.forEach((column) => {
            output += `< td style = "padding: 8px;" > ${getDisplayValue(record, column)}</td > `;
          });
          output += '</tr>';
        });
        output += '</tbody></table>';
      }
    } else {
      // solo dati
      output = {};

      if (options.fieldGM) {
        if (records && records.length === 1) {
          output[options.fieldGM] = records[0][options.fieldGM];
        }
      } else {
        output = [];
        records.forEach((record) => {
          let myrec = {};

          if (options.recordraw) {
            myrec = record;
          } else {
            displayColumns.forEach((column) => {
              const value = record[column];
              if (value !== undefined && value !== null) {
                const type = typeof value;
                if (type === 'number' && !mergedMapping[column]) {
                  myrec[column] = value;
                } else if (type === 'boolean') {
                  myrec[column] = value;
                } else if (value instanceof Date) {
                  myrec[column] = this.formatDate(value);
                } else {
                  myrec[column] = `${getDisplayValue(record, column)}`.trim();
                }
              }
            });
          }
          output.push(myrec);
        });
      }
    }
    return output;
  } catch (error) {
    output = `${error?.response?.data?.error || error?.stack || error.message}`;
    console.error(
      'Errore nel recupero della tabella: ',
      `${error.response.data.error || error.stack || error.message}`
    );
    if (options.outhtml) {
      output = `
    
            <head>
                <meta charset="UTF-8">
                    <title>Errore nel Recupero della Tabella ${options.nameTable}</title>
                    <style>
                        body {
                            font - family: Arial, sans-serif;
                        background-color: #f7f7f7;
                        color: #333;
                        padding: 20px;
                }
                        .error-container {
                            background - color: #ffe6e6;
                        border: 1px solid #ff4d4d;
                        padding: 20px;
                        border-radius: 5px;
                        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                        max-width: 800px;
                        margin: auto;
                }
                        .error-title {
                            font - size: 24px;
                        font-weight: bold;
                        color: #d8000c;
                        margin-bottom: 10px;
                }
                        .error-message {
                            font - size: 16px;
                        white-space: pre-wrap;
                        background: #fff;
                        padding: 10px;
                        border: 1px solid #ddd;
                        border-radius: 3px;
                }
                    </style>
            </head>
            <body>
                <div class="error-container">
                    <div class="error-title">Errore nel Recupero della Tabella ${options.nameTable} con query: ${
        options.where
      }</div>
                    <div class="error-message">
                        ${error.response.data.error || error.stack || error.message}
                    </div>
                </div>
            </body>
`;
    }
    return output;
    // throw new Error("Errore nel recupero della tabella.");
  }
};

const setTableContent = async (options) => {
  try {
    // checkPermissions()

    const esegui = true;

    if (esegui) {
      // Verifica se la tabella esiste
      const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`;
      const checkResponse = await axios.post(
        SERVER_A_URL + '/query',
        { query: checkTableQuery },
        {
          headers: { 'x-api-key': API_KEY },
        }
      );

      if (!checkResponse.data || checkResponse.data.length === 0 || checkResponse.data[0].tableExists === 0) {
        return `La tabella '${options.nameTable}' non esiste.`;
      }

      // Costruisce la query per inserire o aggiornare i record
      let dataQuery = '';
      if (options.insertMode) {
        // Modalità INSERT
        const columns = Object.keys(options.data);
        const values = columns.map((col) => `'${options.data[col]}'`).join(', ');
        dataQuery = `
                INSERT INTO ${options.nameTable} (${columns.join(', ')})
                VALUES (${values});
            `;
      } else {
        // Modalità UPDATE
        const updateFields = Object.keys(options.data)
          .map((col) => `${col} = '${options.data[col]}'`)
          .join(', ');
        const whereClause = options.where ? `WHERE ${options.where}` : '';
        dataQuery = `
                UPDATE ${options.nameTable}
                SET ${updateFields}
                ${whereClause};
            `;
      }

      console.log('dataQuery', dataQuery);

      // Esegue la query per inserire o aggiornare i dati
      const dataResponse = await axios.post(
        SERVER_A_URL + '/query',
        { query: dataQuery },
        {
          headers: { 'x-api-key': API_KEY },
        }
      );

      if (dataResponse.data && dataResponse.data.affectedRows > 0) {
        return `Operazione completata con successo su '${options.nameTable}'.`;
      } else {
        return `Nessun record modificato nella tabella '${options.nameTable}'.`;
      }
    }
  } catch (error) {
    console.error("Errore nell'inserimento o aggiornamento della tabella: ", error.message);
    if (options.outhtml) {
      output = `
            <head>
                <meta charset="UTF-8">
                <title>Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</title>
                <style>
                    body {
                        font-family: Arial, sans-serif;
                        background-color: #f7f7f7;
                        color: #333;
                        padding: 20px;
                    }
                    .error-container {
                        background-color: #ffe6e6;
                        border: 1px solid #ff4d4d;
                        padding: 20px;
                        border-radius: 5px;
                        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                        max-width: 800px;
                        margin: auto;
                    }
                    .error-title {
                        font-size: 24px;
                        font-weight: bold;
                        color: #d8000c;
                        margin-bottom: 10px;
                    }
                    .error-message {
                        font-size: 16px;
                        white-space: pre-wrap;
                        background: #fff;
                        padding: 10px;
                        border: 1px solid #ddd;
                        border-radius: 3px;
                    }
                </style>
            </head>
            <body>
                <div class="error-container">
                    <div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${
                      options.nameTable
                    }</div>
                    <div class="error-message">
                        ${error.response.data.error || error.stack || error.message}
                    </div>
                </div>
            </body>
            `;
      return output;
    }
    return "Errore nell'inserimento o aggiornamento della tabella.";
  }
};
const checkPermissions = async (options) => {
  try {
    const dataQuery = `
        SELECT 
            dp.name AS UserName,
            dp.type_desc AS UserType,
            o.name AS ObjectName,
            p.permission_name,
            p.state_desc AS PermissionState
        FROM
            sys.database_permissions p
        JOIN
            sys.objects o ON p.major_id = o.object_id
        JOIN
            sys.database_principals dp ON p.grantee_principal_id = dp.principal_id
        WHERE
            o.name = 'T_WEB_Articoli';
        `;

    console.log('checkPermissions query:', dataQuery);

    // Esegue la query per inserire o aggiornare i dati
    const dataResponse = await axios.post(
      SERVER_A_URL + '/query',
      { query: dataQuery },
      {
        headers: { 'x-api-key': API_KEY },
      }
    );

    console.log('checkPermissions result:', dataResponse.data);

    if (dataResponse.data && dataResponse.data.affectedRows > 0) {
      return `Operazione completata con successo.`;
    } else {
      return `Nessun permesso.`;
    }
  } catch (error) {
    console.error('Errore nel check dei Permessi: ', error.message);
    if (options.outhtml) {
      output = `
            <head>
                <meta charset="UTF-8">
                <title>Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</title>
                <style>
                    body {
                        font-family: Arial, sans-serif;
                        background-color: #f7f7f7;
                        color: #333;
                        padding: 20px;
                    }
                    .error-container {
                        background-color: #ffe6e6;
                        border: 1px solid #ff4d4d;
                        padding: 20px;
                        border-radius: 5px;
                        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                        max-width: 800px;
                        margin: auto;
                    }
                    .error-title {
                        font-size: 24px;
                        font-weight: bold;
                        color: #d8000c;
                        margin-bottom: 10px;
                    }
                    .error-message {
                        font-size: 16px;
                        white-space: pre-wrap;
                        background: #fff;
                        padding: 10px;
                        border: 1px solid #ddd;
                        border-radius: 3px;
                    }
                </style>
            </head>
            <body>
                <div class="error-container">
                    <div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${
                      options.nameTable
                    }</div>
                    <div class="error-message">
                        ${error.response.data.error || error.stack || error.message}
                    </div>
                </div>
            </body>
            `;
      return output;
    }
    return "Errore nell'inserimento o aggiornamento della tabella.";
  }
};

// Endpoint per mostrare i dati della tabella
exports.viewTable = async (req, res) => {
  try {
    const options = req.body.options;
    const tableContent = await this.getTableContent(options);

    let out = {};

    if (options.outhtml) {
      out = `
                    <h2 class="text-center">Tabella: ${options.nameTable}</h2>
                    <div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
                    <div class="row justify-center">
                        ${tableContent}
                    </div>
                `;
    } else {
      out = tableContent;
    }

    if (tableContent && tableContent.length > 0) {
      if (options.updatelocaldb) {
        this.updateLocalDb(tableContent[0], options);
      }
    }

    return res.send({ code: server_constants.RIS_CODE_OK, data: out });
  } catch (error) {
    console.error('Error: ', error);
    return res.send({ code: server_constants.RIS_CODE_ERR, error });
  }
};

exports.updateLocalDb = async (tableContent, options) => {
  try {
    const Product = require('../models/product');
    const CatProd = require('../models/catprod');

    const code = tableContent.Ean13.trim();

    let risrecUpdated = null;

    const recfound = await Product.findOne({ 'productInfo.code': code }).lean();

    if (recfound) {
      const recproductInfo = recfound.productInfo;
      ListaArgomenti = tableContent.ListaArgomenti;

      let arrayPulito = ListaArgomenti.trim() // Rimuove gli spazi all'inizio e alla fine
        .replace(/[\(\)]/g, '') // Rimuove le parentesi tonde
        .split(','); // Divide la stringa in un array usando la virgola come separatore

      if (arrayPulito && arrayPulito.length > 0) {
        let aggiornacat = false;
        const precCatProds = recfound.productInfo.idCatProds;
        let reccatprods = [];
        for (let i = 0; i < arrayPulito.length; i++) {
          const idArgomento = parseInt(arrayPulito[i]);
          reccateg = await CatProd.findOne({ idArgomento });

          if (reccateg) {
            // aggiungi solo se non esiste già
            if (!reccatprods.includes(reccateg._id)) {
              reccatprods.push(reccateg._id);
            }
          }

          if (!reccateg?.idArgomento) {
            // Se non c'è l'argomento, allora lo cerco nel DB
            const recarg = await T_Web_Argomenti.findOne({ Descrizione: reccateg.name }).lean();
            reccateg.idArgomento = recarg.IdArgomento;
            await reccateg.save();
          }
        }

        // ora controlla se l'array reccatprods e' diverso da precCatProds
        if (reccatprods.length !== precCatProds.length) {
          aggiornacat = true;
        } else {
          for (let i = 0; i < reccatprods.length; i++) {
            if (reccatprods[i].toString() !== precCatProds[i].toString()) {
              aggiornacat = true;
              break;
            }
          }
        }

        if (aggiornacat) {
          recproductInfo.idCatProds = reccatprods;
          aggiorna = true;
        }
      }

      if (tableContent.DataPubblicazione.trim()) {
        recproductInfo.date_pub = new Date(tools.convertiDataItaliana(tableContent.DataPubblicazione.trim()).date);
        // convert data to timestamp
        recproductInfo.date_pub_ts = recproductInfo.date_pub.getTime();
        aggiorna = true;
      }

      if (aggiorna) {
        risrecUpdated = await Product.findOneAndUpdate(
          { _id: recfound._id },
          { $set: { productInfo: recproductInfo } },
          { new: true, upsert: true }
        );
      }

      return risrecUpdated;
    }
  } catch (e) {
    console.error('Error: ', e);
    return null;
  }
};

// Endpoint per mostrare i dati della tabella
exports.queryTable = async (req, res) => {
  try {
    const options = req.body.options;
    const tableContent = await this.getTableContent(options);

    let out = {};

    if (options.outhtml) {
      out = `
                    <h2>Tabella: ${options.nameTable}</h2>
                    <div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
                    ${tableContent}
`;
    } else {
      out = tableContent;
    }

    return res.send({ code: server_constants.RIS_CODE_OK, data: out });
  } catch (error) {
    console.error('Error: ', error);
    return res.send({ code: server_constants.RIS_CODE_ERR, error });
  }
};
// Endpoint per salvare i dati di una tabella
exports.saveTable = async (req, res) => {
  try {
    const options = req.body.options;
    const tableContent = await setTableContent(options);

    let out = {};

    if (options.outhtml) {
      out = `
                    <h2 class="text-center">Tabella: ${options.nameTable}</h2>
                    <div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
                    <div class="row justify-center">
                        ${tableContent}
                    </div>
                `;
    } else {
      out = tableContent;
    }

    return res.send({ code: server_constants.RIS_CODE_OK, data: out });
  } catch (error) {
    console.error('Error: ', error);
    return res.send({ code: server_constants.RIS_CODE_ERR, error });
  }
};

exports.mssqlmigrateTables = async (req) => {
  const MssqlMigrator = require('../modules/MssqlMigrator'); // Importa la classe Macro

  try {
    const options = req.body.mydata.options;
    let listaTabelle = [];
    if (options?.parte1 || options?.tutte) {
      listaTabelle.push({ table: 'T_WEB_TitoliOriginali', usaDataOra: true, fieldId: 'IdTitoloOriginale' });
      listaTabelle.push({ table: 'T_WEB_TestateOrdini', usaDataOra: false });
      listaTabelle.push({ table: 'T_WEB_Ordini', usaDataOra: false });
      listaTabelle.push({ table: 'T_WOO_TestateOrdini', usaDataOra: false });
      listaTabelle.push({ table: 'T_WOO_Ordini', usaDataOra: false });
      listaTabelle.push({ table: 'T_WEB_Articoli', usaDataOra: true, fieldId: 'IdArticolo' });
    }

    if (options?.parte2 || options?.tutte) {
      listaTabelle.push({ table: 'T_WEB_Disponibile', usaDataOra: true, fieldId: 'Codice' });
      listaTabelle.push({ table: 'T_WEB_Argomenti', usaDataOra: true, fieldId: 'IdArgomento' });
      listaTabelle.push({ table: 'T_WEB_ClientiInternet', usaDataOra: false });
      listaTabelle.push({ table: 'T_WOO_Clienti', usaDataOra: false });
      listaTabelle.push({ table: 'T_WEB_Autori', usaDataOra: true, fieldId: 'IdAutore' });
    }
    if (options?.parte3 || options?.tutte) {
      listaTabelle.push({ table: 'T_WEB_Collane', usaDataOra: true, fieldId: 'IdCollana' });
      listaTabelle.push({ table: 'T_WEB_MarchiEditoriali', usaDataOra: true, fieldId: 'IdMarchioEditoriale' });
      listaTabelle.push({ table: 'T_WEB_StatiProdotto', usaDataOra: true, fieldId: 'IdStatoProdotto' });
      listaTabelle.push({ table: 'T_WEB_TipiFormato', usaDataOra: true, fieldId: 'IdTipoFormato' });
      listaTabelle.push({ table: 'T_WEB_Tipologie', usaDataOra: true, fieldId: 'IdTipologia' });
      listaTabelle.push({ table: 'T_WEB_ArticoliFatturati', usaDataOra: false });
      listaTabelle.push({ table: 'T_WEB_IdInternetFatturati', usaDataOra: false });
      listaTabelle.push({ table: 'T_WEB_Edizioni', usaDataOra: true, fieldId: 'IdEdizione' });
      listaTabelle.push({ table: 'T_WEB_Contratti', usaDataOra: true, fieldId: 'IdArticolo' });
    }
    if (options?.test) {
      listaTabelle.push({ table: 'T_WEB_Articoli', usaDataOra: true, fieldId: 'IdArticolo' });
    }

    const migrator = new MssqlMigrator();
    return await migrator.migrateTables(listaTabelle);
  } catch (e) {
    console.error(e.message);
    return 'Errore: ' + e.message;
  }
};
exports.updateAllBook = async (idapp, options) => {
  const Macro = require('../modules/Macro'); // Importa la classe Macro

  try {
    const macro = new Macro(idapp); // Crea un'istanza della classe Macro
    options.idapp = idapp;
    return await macro.updateLocalDbFromGM_T_Web_Articoli(options);
  } catch (e) {
    console.error(e.message);
    return e.message;
  }
};

exports.updateAllBookRoute = async (req, res) => {
  try {
    const idapp = req.body.idapp;
    const options = req.body.options;
    const result = await this.updateAllBook(idapp, options);

    return res.status(200).send({ data: result });
  } catch (e) {
    console.error(e.message);
    if (res) {
      return res.status(400).send(e);
    }
  }
};
