const express = require('express');
const router = express.Router();
const db = require('../db');
const fs = require('fs');
const path = require('path');
const serverError = require('../utils/serverError');
const videoManager = require('../src/video/videoManager');
const measureManager = require('../src/measure/measureManager');
const dbTester = require('../test/tester');

/**
 * @swagger
 * /videos:
 *   get:
 *     summary: Récupérer toutes les vidéos
 *     description: Récupère toutes les vidéos de la base de données.
 *     responses:
 *       200:
 *         description: Une liste de vidéos.
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 type: object
 *                 properties:
 *                   id:
 *                     type: integer
 *                   project_id:
 *                     type: integer
 *                   measurement_ids:
 *                     type: string
 *                   video_path:
 *                     type: string
 *                   start_timestamp:
 *                     type: string
 *                   end_timestamp:
 *                     type: string
 *                   image_count:
 *                     type: integer
 *                   resolution:
 *                     type: string
 *                   duration:
 *                     type: number
 *                   fps:
 *                     type: number
 *                   status:
 *                     type: integer
 *                   name:
 *                     type: string
 *       500:
 *         description: Erreur serveur.
 */
router.get('/videos', (req, res) => {
   const query = 'SELECT * FROM public.videos';
   db.query(query, (err, results) => {
      if (err) {
         serverError.sendError('Erreur lors de la récupération des vidéos:', res, err);
      }
      res.json(results.rows);
   });
});

/**
 * @swagger
 * /videos/{id}:
 *   get:
 *     summary: Récupérer une vidéo par ID
 *     description: Récupère une vidéo spécifique en utilisant son ID.
 *     parameters:
 *       - in: path
 *         name: id
 *         schema:
 *           type: integer
 *         required: true
 *         description: ID de la vidéo
 *     responses:
 *       200:
 *         description: Une vidéo.
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 id:
 *                   type: integer
 *                 project_id:
 *                   type: integer
 *                 measurement_ids:
 *                   type: string
 *                 video_path:
 *                   type: string
 *                 start_timestamp:
 *                   type: string
 *                 end_timestamp:
 *                   type: string
 *                 image_count:
 *                   type: integer
 *                 resolution:
 *                   type: string
 *                 duration:
 *                   type: number
 *                 fps:
 *                   type: number
 *                 status:
 *                   type: integer
 *                 name:
 *                   type: string
 *       400:
 *         description: ID de vidéo invalide.
 *       500:
 *         description: Erreur serveur.
 */
router.get('/videos/:id', (req, res) => {
   const videoId = req.params.id;
   if (!videoId || isNaN(videoId)) {
      return res.status(400).json({ error: 'Invalid video ID' });
   }
   const query = 'SELECT * FROM public.videos WHERE id = $1';
   db.query(query, [videoId], (err, results) => {
      if (err) {
         serverError.sendError('Erreur lors de la récupération de la vidéo:', res, err);
      }
      res.json(results.rows);
   });
});

/**
 * @swagger
 * /videos:
 *   post:
 *     summary: Créer une nouvelle vidéo
 *     description: Crée une nouvelle vidéo avec les informations fournies.
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               project_id:
 *                 type: integer
 *               measurement_ids:
 *                 type: string
 *               name:
 *                 type: string
 *               resolution:
 *                 type: string
 *               duration:
 *                 type: number
 *     responses:
 *       200:
 *         description: Vidéo créée avec succès.
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 message:
 *                   type: string
 *                 video:
 *                   type: object
 *                   properties:
 *                     project_id:
 *                       type: integer
 *                     measurement_ids:
 *                       type: string
 *                     name:
 *                       type: string
 *                     resolution:
 *                       type: string
 *                     duration:
 *                       type: number
 *       400:
 *         description: Tous les champs sont requis.
 *       500:
 *         description: Erreur serveur.
 */
router.post('/videos', (req, res) => {
   const { project_id, measurement_ids, name, resolution, duration } = req.body;
   console.log('Creating video:', req.body);
   if (!project_id || !measurement_ids || !name || !resolution || !duration) {
      return res.status(400).json({ error: 'Tous les champs sont requis.' });
   }

   console.log('Creating video with measurements:', measurement_ids);

   videoManager.createVideoProject(project_id, measurement_ids, name, resolution, duration).then(video => {
      res.json({ message: 'Vidéo créée avec succès', video });
   }).catch(err => {
      console.error('Erreur lors de la création de la vidéo:', err);
   }).catch(err => {
      console.error('Erreur lors de la création de la vidéo:', err);
      res.status(500).json({ error: 'Erreur lors de la création de la vidéo' });
   });
});


/**
 * @swagger
 * /videos/{id}:
 *   delete:
 *     summary: Supprimer une vidéo par ID
 *     description: Supprime une vidéo spécifique en utilisant son ID.
 *     parameters:
 *       - in: path
 *         name: id
 *         schema:
 *           type: integer
 *         required: true
 *         description: ID de la vidéo
 *     responses:
 *       200:
 *         description: Vidéo supprimée avec succès.
 *       400:
 *         description: ID de vidéo invalide.
 *       404:
 *         description: Aucune vidéo trouvée avec cet ID.
 *       500:
 *         description: Erreur serveur.
 */
router.delete('/videos/:id', (req, res) => {
   const videoId = req.params.id;
   if (!videoId || isNaN(videoId)) {
      return res.status(400).json({ error: 'Invalid video ID' });
   }
   videoManager.deleteVideoProject(videoId).then(() => {
      res.json({ message: 'Vidéo supprimée avec succès' });
   }).catch(err => {
      console.error('Erreur lors de la suppression de la vidéo:', err);
   });
});

/**
 * @swagger
 * /videos/file/{video_id}:
 *   get:
 *     summary: Retrieve a video by video ID
 *     parameters:
 *       - in: path
 *         name: video_id
 *         required: true
 *         schema:
 *           type: string
 *         description: The video ID
 *     responses:
 *       200:
 *         description: A video file
 *         content:
 *           application/octet-stream:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: Video not found
 *       400:
 *         description: Video not yet produced
 */
router.get('/videos/file/:video_id', (req, res) => {
   const videoId = req.params.video_id;
   const query = 'SELECT video_file, status FROM public.videos WHERE id = $1';
   db.query(query, [videoId], (err, results) => {
       if (err) {
           return serverError.sendError('Error getting video:', res, err);
       }
       if (results.rows.length === 0) {
           return res.status(404).json({ error: 'Video not found' });
       }
       const video = results.rows[0];
       if (video.status === 0) {
           return res.status(400).json({ error: 'Video not yet produced' });
       }
       const videoPath = video.video_file;
       console.log('Video path:', videoPath);
       fs.access(videoPath, fs.constants.F_OK, (err) => {
           if (err) {
               console.error('Video not found:', err);
               return res.status(404).json({ error: 'Video not found' });
           }
           res.download(videoPath);
       });
   });
});

/**
 * @swagger
 * /videos/render/{video_id}:
 *   post:
 *     summary: Render a video by video ID
 *     parameters:
 *       - in: path
 *         name: video_id
 *         required: true
 *         schema:
 *           type: string
 *         description: The video ID
 *     responses:
 *       200:
 *         description: Render process started
 *       404:
 *         description: Video not found
 *       500:
 *         description: Server error
 */
router.post('/videos/render/:video_id', async (req, res) => {
   const videoId = req.params.video_id;
   const query = 'SELECT measurement_ids, project_id FROM public.videos WHERE id = $1';

   db.query(query, [videoId], async (err, results) => {
      if (err) {
         return serverError.sendError('Error getting video:', res, err);
      }
      if (results.rows.length === 0) {
         return res.status(404).json({ error: 'Video not found' });
      }

      const measurementIds = results.rows[0].measurement_ids;
      const project_id = results.rows[0].project_id;
      console.log('Measurement IDs:', measurementIds);
      console.log('Project ID:', project_id);

      try {
         const pathList = await measureManager.getPathList(measurementIds, project_id);
         console.log('Path list:', pathList);
         res.json({ message: 'Render process started' });

         const videoFile = await videoManager.createVideoWithList(project_id, pathList);
         console.log('Video file:', videoFile);

         await videoManager.updateVideoFile(videoId, videoFile);

         console.log('Video rendering complete');

         //changer status de la vidéo à 1
         const query = 'UPDATE public.videos SET status = 1 WHERE id = $1';
         db.query(query, [videoId], (err, results) => {
            if (err) {
               return serverError.sendError('Error updating video status:', res, err);
            }
            console.log('Video status updated:', results.rows[0]);
         });
      } catch (err) {
         console.error('Error during video rendering:', err);
         res.status(500).json({ error: 'Error during video rendering' });
      }
   });
});

/**
 * @swagger
 * /videos/reset/{video_id}:
 *   get:
 *     summary: Reset the status of a video by video ID
 *     parameters:
 *       - in: path
 *         name: video_id
 *         required: true
 *         schema:
 *           type: string
 *         description: The video ID
 *     responses:
 *       200:
 *         description: Video reset successfully
 *       404:
 *         description: Video not found
 *       500:
 *         description: Server error
 */
router.get('/videos/reset/:video_id', (req, res) => {
   const videoId = req.params.video_id;
   const query = 'SELECT video_file FROM public.videos WHERE id = $1';

   db.query(query, [videoId], (err, results) => {
      if (err) {
         return serverError.sendError('Error getting video:', res, err);
      }
      if (results.rows.length === 0) {
         return res.status(404).json({ error: 'Video not found' });
      }

      const videoFile = results.rows[0].video_file;
      fs.unlink(videoFile, (err) => {
         if (err) {
            console.error('Error deleting video file:', err);
            return res.status(500).json({ error: 'Error deleting video file' });
         }

         const updateQuery = 'UPDATE public.videos SET status = 0, video_file = NULL WHERE id = $1';
         db.query(updateQuery, [videoId], (err) => {
            if (err) {
               return serverError.sendError('Error resetting video status:', res, err);
            }
            res.json({ message: 'Video reset successfully' });
         });
      });
   });
});


/**
 * @swagger
 * /cat:
 *   get:
 *     summary: Retrieve a cat video
 *     responses:
 *       200:
 *         description: A cat video
 *         content:
 *           application/octet-stream:
 *             schema:
 *               type: string
 *               format: binary
 *       404:
 *         description: Video not found
 */
router.get('/cat', (_, res) => {
   const videoPath = dbTester.getCatVideo();
   fs.access(videoPath, fs.constants.F_OK, (err) => {
      if (err) {
         console.error('Video not found:', err);
         return res.status(404).json({ error: 'Video not found' });
      }
      res.download(videoPath);
   });
});

module.exports = router;
