const express = require('express');
const { authenticate, authenticate_noerror } = require('../middleware/authenticate');

const router = express.Router();

const templatesRouter = require('../routes/templates');
const postersRouter = require('../routes/posters');
const assetsRouter = require('../routes/assets');

const PageView = require('../models/PageView');

// const { Groq } = require('groq-sdk');

const fal = require('@fal-ai/client');


const imageGenerator = require('../services/imageGenerator'); // Assicurati che il percorso sia corretto

const posterEditor = require('../services/PosterEditor'); // <--- Importa la nuova classe

const multer = require('multer');
const XLSX = require('xlsx');

const upload = multer({ dest: 'uploads/' });

const Product = require('../models/product');
const Author = require('../models/author');

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

const { MyPage } = require('../models/mypage');
const { MyElem } = require('../models/myelem');

const axios = require('axios');

const trasportiRoutes = require('../routes/trasportiRoutes');
router.use('/trasporti', trasportiRoutes);


// Importa le routes video
const videoRoutes = require('../routes/videoRoutes');

// Monta le routes video
router.use('/video', videoRoutes);


router.use('/templates', authenticate, templatesRouter);
router.use('/posters', authenticate, postersRouter);
router.use('/assets', authenticate, assetsRouter);

router.post('/test-lungo', authenticate, (req, res) => {
  const timeout = req.body.timeout;

  console.log(`🕙 Richiesta iniziata con timeout=${timeout}`);

  // Simuliamo un'elaborazione lunga
  const durataMs = timeout - 2000;
  setTimeout(() => {
    console.log(`✅ Elaborazione completata di ${durataMs} ms`);
    res.json({ ok: true, message: `✅ Richiesta completata con successo! (${durataMs})` });
  }, durataMs);

  // Verifico se la richiesta  va a buon fine
  setTimeout(() => {
    if (!res.headersSent) {
      res.status(500).json({ ok: false, message: "❌ Errore durante l'elaborazione della richiesta!" });
    }
  }, durataMs + 1000);
});

router.post('/track-pageview', authenticate_noerror, async (req, res) => {
  const { url, userAgent, idapp, referrer } = req.body;
  const ip = req.ip || req.headers['x-forwarded-for'] || 'unknown';

  try {
    const pageView = new PageView({
      url,
      ip,
      idapp,
      referrer,
      userId: req.user ? req.user._id : '',
      username: req.user ? req.user.username : '',
      userAgent,
    });

    await pageView.save();

    return res.status(200).json({ message: '' });
  } catch (error) {
    console.error('Errore nel salvataggio della visita:', error);
    return res.status(500).json({ error: 'Impossibile registrare la visita' });
  }
});

router.get('/pageviews/stats', authenticate_noerror, async (req, res) => {
  const { userId, idapp, unique } = req.query;

  try {
    const matchStage = { idapp };
    if (userId) {
      matchStage.$or = [{ userId }, { username: userId }];
    }

    // Definiamo la base della pipeline
    const basePipeline = [{ $match: matchStage }];

    const today = startOfDay(new Date());
    const weekAgo = startOfDay(subDays(new Date(), 7));
    const monthAgo = startOfDay(subDays(new Date(), 30));

    // Funzione dinamica per creare pipeline di conteggio
    const countStage = (date) => {
      const match = { timestamp: { $gte: date } };
      if (!unique) {
        return [{ $match: match }, { $count: 'count' }];
      }
      return [
        { $match: match },
        {
          $group: {
            _id: {
              url: '$url',
              user: { $ifNull: ['$userId', '$ip'] },
              date: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
            },
          },
        },
        { $count: 'count' },
      ];
    };

    // Pipeline completa
    const timeStatsPipeline = [
      ...basePipeline,
      {
        $facet: {
          total: !unique
            ? [{ $count: 'count' }]
            : [
                {
                  $group: {
                    _id: {
                      url: '$url',
                      user: { $ifNull: ['$userId', '$ip'] },
                      date: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
                    },
                  },
                },
                { $count: 'count' },
              ],
          today: countStage(today),
          week: countStage(weekAgo),
          month: countStage(monthAgo),
        },
      },
    ];

    // Eseguiamo solo la parte delle statistiche temporali
    const timeStatsResult = await PageView.aggregate(timeStatsPipeline);

    // Ora costruiamo la pipeline completa per topPages (con o senza unique)
    let topPagesPipeline = [...basePipeline];

    if (unique) {
      topPagesPipeline = [
        ...topPagesPipeline,
        {
          $group: {
            _id: {
              url: '$url',
              userId: { $ifNull: ['$userId', '$ip'] },
              date: {
                $dateToString: {
                  format: '%Y-%m-%d',
                  date: '$timestamp',
                },
              },
            },
          },
        },
        { $replaceRoot: { newRoot: '$_id' } },
      ];
    }

    // Aggiungi il group finale per contare le pagine
    const topPagesResult = await PageView.aggregate([
      ...topPagesPipeline,
      {
        $group: {
          _id: '$url',
          count: { $sum: 1 },
        },
      },
      { $sort: { count: -1 } },
      { $limit: 10 },
    ]);

    // Formattazione dei risultati
    const formatCount = (arr) => (arr && arr.length > 0 ? arr[0].count || 0 : 0);

    const stats = {
      total: formatCount(timeStatsResult[0]?.total),
      today: formatCount(timeStatsResult[0]?.today),
      week: formatCount(timeStatsResult[0]?.week),
      month: formatCount(timeStatsResult[0]?.month),
      topPages: topPagesResult,
    };

    res.json(stats);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Errore nel calcolo delle statistiche' });
  }
});

function startOfDay(date) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}

function subDays(date, days) {
  const newDate = new Date(date);
  newDate.setDate(newDate.getDate() - days);
  return newDate;
}

router.delete('/mypage/:id', authenticate, async (req, res) => {
  try {
    const { id } = req.params;

    // Trova il record di MyPage da cancellare
    const pageToDelete = await MyPage.findByIdAndDelete(id);

    if (!pageToDelete) return res.status(404).json({ error: 'Pagina non trovata' });
    if (!pageToDelete) {
      return res.status(404).json({ error: 'Pagina non trovata' });
    } else {
      await MyElem.deleteAllFromThisPage(id);
    }

    res.json({ message: `Pagina eliminata con successo: ${pageToDelete.path}` });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Errore durante l'eliminazione della pagina" });
  }
});

router.get('/pageviews/users', authenticate_noerror, async (req, res) => {
  try {
    const { idapp } = req.query;

    // Trova tutte le entry con idapp e prendi userId e username
    const usersData = await PageView.find({ idapp }, { userId: 1, username: 1, _id: 0 }).lean();

    // Usa un Map per garantire unicità basata su userId
    const uniqueUsersMap = new Map();

    usersData.forEach(({ userId, username }) => {
      if (userId && !uniqueUsersMap.has(userId)) {
        uniqueUsersMap.set(userId, { userId, username });
      }
    });

    // Converte la Map in array
    const uniqueUsers = Array.from(uniqueUsersMap.values());

    res.json(uniqueUsers);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Errore nel recupero degli utenti' });
  }
});

router.get('/pageviews/weekly-top-pages', authenticate_noerror, async (req, res) => {
  const { idapp, userId, unique, year, week } = req.query;

  try {
    const matchStage = { idapp };
    if (userId) {
      matchStage.$or = [{ userId }, { username: userId }];
    }

    const pipeline = [];

    // Filtro base
    pipeline.push({ $match: matchStage });

    // Estrai settimana e anno
    pipeline.push({
      $addFields: {
        week: { $isoWeek: '$timestamp' },
        year: { $isoWeekYear: '$timestamp' },
      },
    });

    // Filtra per settimana e anno se specificati
    if (year && week) {
      pipeline.push({
        $match: {
          year: parseInt(year),
          week: parseInt(week),
        },
      });
    }

    if (unique === 'true') {
      // Visite uniche: 1 per utente/giorno/pagina
      pipeline.push({
        $group: {
          _id: {
            url: '$url',
            user: { $ifNull: ['$userId', '$ip'] },
            day: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
          },
        },
      });

      // Riformatta per conteggio
      pipeline.push({
        $group: {
          _id: '$_id.url',
          count: { $sum: 1 },
        },
      });
    } else {
      // Visite totali: tutte le occorrenze
      pipeline.push({
        $group: {
          _id: '$url',
          count: { $sum: 1 },
        },
      });
    }

    // Ordina per numero visite
    pipeline.push({ $sort: { count: -1 } });

    // Aggiungi metadati settimana/anno se presenti
    if (year && week) {
      pipeline.push({
        $addFields: {
          year: parseInt(year),
          week: parseInt(week),
        },
      });
    }

    const result = await PageView.aggregate(pipeline);

    res.json(
      result.map((r) => ({
        url: r._id,
        count: r.count,
        year: r.year,
        week: r.week,
      }))
    );
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Errore nel calcolo delle statistiche settimanali' });
  }
});

router.post('/api/convert-csv-to-xls', upload.single('csv'), (req, res) => {
  try {
    const csvFilePath = req.file.path;

    // Leggi il CSV con SheetJS
    const csvData = fs.readFileSync(csvFilePath, 'utf-8');
    const worksheet = XLSX.utils.csv_to_sheet(csvData);

    // Crea un file Excel
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

    // Imposta la risposta come file XLS
    const xlsFilePath = path.join(__dirname, 'converted', 'output.xls');
    XLSX.writeFile(workbook, xlsFilePath);

    // Restituisci il file XLS al frontend come risposta
    res.download(xlsFilePath, 'converted-file.xls', (err) => {
      if (err) {
        console.error('Errore nel download del file:', err);
        res.status(500).send('Errore nel download del file');
      }

      // Pulisci il file temporaneo
      fs.unlinkSync(csvFilePath);
      fs.unlinkSync(xlsFilePath);
    });
  } catch (error) {
    console.error('Errore nella conversione del file:', error);
    res.status(500).send('Errore nella conversione del file');
  }
});

// Funzione per "escapare" i caratteri speciali
const escapeRegExp = (string) => {
  return string.replace(/[.*+?^=!:${}()|\[\]\/\\]/g, '\\$&'); // Escape dei caratteri speciali
};

// API per la ricerca dei libri
router.post('/search-books', authenticate, async (req, res) => {
  const { books } = req.body;

  if (!books || books.length === 0) {
    return res.status(400).json({ error: 'Nessun dato fornito per la ricerca' });
  }

  try {
    // Crea un array per raccogliere i risultati
    let results = [];

    let product = null;

    for (const book of books) {
      let trovatoISBN = false;
      let trovato = false;
      let productfind = null;

      for (let field of book) {
        field = field.trim();
        let valido = typeof field === 'string' && field.length > 4 && field.length < 50;
        if (valido) {
          // Cerca il primo record che corrisponde per ISBN o titolo
          if (true) {
            if (!trovatoISBN) {
              let productInfoarrISBN = await Product.find({
                'productInfo.code': field.toUpperCase(),
                $or: [{ deleted: false }, { deleted: { $exists: false } }],
              }).exec();

              // Priorità se lo trovo per ISBN:
              if (productInfoarrISBN.length === 1) {
                productfind = productInfoarrISBN[0];
                trovatoISBN = true;
                trovato = true;
              }
            }
            if (!trovatoISBN && !trovato) {
              // Prima cerca se è esattamente cosi
              let productarrTitle = await Product.find({
                $or: [{ deleted: false }, { deleted: { $exists: false } }],
                'productInfo.name': field,
              }).exec();
              if (productarrTitle.length === 1) {
                productfind = productarrTitle[0];
                trovato = true;
              } else {
                if (productarrTitle.length > 1) {
                  // Prendi l'Ultimo !
                  productfind = productarrTitle[productarrTitle.length - 1];
                  trovato = true;
                }
              }
              if (!trovato) {
                // Altrimenti per Titolo
                productarrTitle = await Product.find({
                  $or: [{ deleted: false }, { deleted: { $exists: false } }],
                  'productInfo.name': new RegExp(`.*${escapeRegExp(tools.removeAccents(field.toUpperCase()))}.*`, 'i'),
                }).exec();
                if (productarrTitle.length === 1) {
                  productfind = productarrTitle[0];
                  trovato = true;
                } else {
                  if (productarrTitle.length > 1) {
                    // Prendi l'Ultimo !
                    productfind = productarrTitle[productarrTitle.length - 1];
                    trovato = true;
                  }
                }
              }
            }
          }
        }
      }

      if (trovato) {
        if (productfind) {
          product = await Product.findOne({ _id: productfind._id }).lean().exec();
          if (product) {
            const existingResult = results.find((r) => r._id.toString() === product._id.toString());
            if (!existingResult) {
              let titolo = product.productInfo.name;
              results.push({
                ...product,
                _id: product._id,
                title: titolo,
                isbn: product.isbn,
                authors: await Promise.all(
                  product.productInfo.idAuthors.map(async (authorId) => {
                    const author = await Author.findById(authorId).exec();
                    return author ? `${author.name} ${author.surname}`.trim() : '';
                  })
                ),
                select: true,
              });
            }
          }
        }
      }
      //
    }

    res.status(200).json(results); // Restituisci i risultati trovati
  } catch (err) {
    console.error('Errore durante la ricerca dei libri:', err);
    res.status(500).json({ error: 'Errore interno del server' });
  }
});

router.post('/chatbot', authenticate, async (req, res) => {
  try {
    const response = await axios.post('http://localhost:5005/webhooks/rest/webhook', {
      sender: 'user',
      message: req.body.payload.message,
    });

    res.json(response.data);
  } catch (error) {
    console.error(error?.message);
    res.status(500).send('Errore nella comunicazione con Rasa');
  }
});

router.post('/generateposter', async (req, res) => {
  const { 
    titolo, data, ora, luogo, descrizione, contatti, fotoDescrizione, stile, 
    provider = 'hf' // Default a HF (Gratis)
  } = req.body;

  // 1. Prompt per l'AI: Chiediamo SOLO lo sfondo, VIETIAMO il testo.
  // Questo garantisce che Flux si concentri sulla bellezza dell'immagine.
  const promptAI = `Vertical event poster background, ${stile || 'modern style, vivid colors'}. 
  Subject: ${fotoDescrizione || 'abstract artistic shapes'}. 
  Composition: Central empty space or clean layout suitable for overlaying text later. 
  NO TEXT, NO LETTERS, clean illustration, high quality, 4k.`;

  try {
    console.log('1. Generazione Sfondo AI...');
    // Genera solo l'immagine base
    const rawImageUrl = await imageGenerator.generate(provider, promptAI);

    console.log('2. Composizione Grafica Testi...');
    // Sovrapponi i testi con Canvas
    const finalPosterBase64 = await posterEditor.createPoster(rawImageUrl, {
      titolo,
      data,
      ora,
      luogo,
      contatti
    });

    res.json({ 
      success: true, 
      imageUrl: finalPosterBase64, // Restituisce l'immagine completa in base64
      step: 'AI + Canvas Composition'
    });

  } catch (err) {
    console.error('Errore:', err.message);
    res.status(500).json({ error: err.message });
  }
});



module.exports = router;
