import { db } from './db.js';
import { errorHandler } from './utils.js';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import SFTPClient from 'ssh2-sftp-client';

/**
 * @swagger
 * tags:
 *   name: Partner
 *   description: Partner management and operations
 */

// Multer configuration for local file storage before uploading to the remote server
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const tempDirectory = path.resolve('uploads');
    if (!fs.existsSync(tempDirectory)) {
      fs.mkdirSync(tempDirectory, { recursive: true });
    }
    cb(null, tempDirectory);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
    cb(null, `${uniqueSuffix}-${file.originalname}`);
  }
});

const upload = multer({ storage });

// SFTP Configuration
const sftpConfig = {
  host: process.env.HOST, // Replace with your server IP or domain
  port: process.env.REMOTE_PORT, // Default SFTP port
  username: process.env.REMOTE_USER, // Replace with your server username
  password: process.env.PASSWORD, // Replace with your server password
};

// Remote directory where files will be uploaded
const remoteDirectory = '/var/www/react/goodpark.fr/web/cdm';

/**
 * @swagger
 * /partner/upload:
 *   post:
 *     summary: Upload a file and save it on the remote server
 *     tags: [Partner]
 *     requestBody:
 *       required: true
 *       content:
 *         multipart/form-data:
 *           schema:
 *             type: object
 *             properties:
 *               file:
 *                 type: string
 *                 format: binary
 *                 description: The file to upload
 *     responses:
 *       200:
 *         description: File uploaded successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 message:
 *                   type: string
 *                   example: File uploaded successfully
 *                 remoteFilePath:
 *                   type: string
 *                   example: /var/www/react/goodpark.fr/web/cdm/your-uploaded-file.jpg
 *       400:
 *         description: Bad request
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 error:
 *                   type: string
 *                   example: Invalid file format or missing file
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 error:
 *                   type: string
 *                   example: Failed to upload the file
 */
export const uploadFile = async (req, res) => {
  const singleUpload = upload.single('file');

  singleUpload(req, res, async (err) => {
    if (err) {
      return errorHandler(res, err.message || 'File upload failed', 400);
    }

    const localFilePath = req.file.path;
    console.log(req.file);
    console.log(req.file.filename);
    const remoteFileName = path.basename(req.file.originalname);
    const remoteFilePath = path.join(remoteDirectory, remoteFileName);

    const sftp = new SFTPClient();

    try {
      // Connect to the remote server
      console.log('Connecting to SFTP with config:', sftpConfig);
      await sftp.connect(sftpConfig);
      console.log('SFTP connection established');

      // Upload the file to the remote server
      await sftp.put(localFilePath, remoteFilePath);

      // Respond with the remote file path
      res.status(200).json({
        message: 'File uploaded successfully',
        remoteFilePath
      });

      // Optionally, delete the local file after uploading
      fs.unlinkSync(localFilePath);
    } catch (error) {
      console.error('SFTP Upload Error:', error);
      errorHandler(res, error.message || 'Failed to upload the file to the remote server', 500);
    } finally {
      await sftp.end();
    }
  });
};





// **********
// AD TYPE ROUTES
// **********
/**
 * @swagger
 * /adtype/all:
 *   get:
 *     summary: Get all ad types
 *     tags: [AdType]
 *     responses:
 *       200:
 *         description: A list of ad types
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/AdType'
 */
export const allAdTypes = (req, res) => {
  const query = 'SELECT * FROM adtype';
  db.query(query, (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results);
  });
};

/**
 * @swagger
 * /adtype/byId/{id}:
 *   get:
 *     summary: Get ad type by ID
 *     tags: [AdType]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Ad type ID
 *     responses:
 *       200:
 *         description: Ad type retrieved successfully
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/AdType'
 */
export const adTypeById = (req, res) => {
  const query = 'SELECT * FROM adtype WHERE id = ?';
  db.query(query, [req.params.id], (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results[0]);
  });
};

// POST //

/**
 * @swagger
 * /adtype/create:
 *   post:
 *     summary: Create a new ad type
 *     tags: [AdType]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/AdType'
 *           example:
 *             label: "Banner Ad"
 *             description: "A large banner ad"
 *     responses:
 *       201:
 *         description: Ad type created successfully
 */
export const createAdType = (req, res) => {
  const query = 'INSERT INTO adtype SET ?';
  db.query(query, req.body, (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.status(201).json({ id: result.insertId, ...req.body });
  });
};

// PUT //

/**
 * @swagger
 * /adtype/update/{id}:
 *   put:
 *     summary: Update an existing ad type
 *     tags: [AdType]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Ad type ID
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/AdType'
 *           example:
 *             label: "Updated Banner Ad"
 *             description: "Updated description for the ad"
 *     responses:
 *       200:
 *         description: Ad type updated successfully
 */
export const updateAdType = (req, res) => {
  const query = 'UPDATE adtype SET ? WHERE id = ?';
  db.query(query, [req.body, req.params.id], (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.json({ message: 'Ad type updated successfully' });
  });
};

// DELETE //

/**
 * @swagger
 * /adtype/delete/{id}:
 *   delete:
 *     summary: Delete ad type by ID
 *     tags: [AdType]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Ad type ID
 *     responses:
 *       200:
 *         description: Ad type deleted successfully
 */
export const deleteAdType = (req, res) => {
  const query = 'DELETE FROM adtype WHERE id = ?';
  db.query(query, [req.params.id], (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.json({ message: 'Ad type deleted successfully' });
  });
};

// **********
// AD ROUTES
// **********

// GET //

/**
 * @swagger
 * /ad/nearby:
 *   get:
 *     summary: Get ads near a specific location
 *     tags: [Ad]
 *     parameters:
 *       - in: query
 *         name: latitude
 *         schema:
 *           type: number
 *         required: true
 *         description: Latitude of the user's location
 *       - in: query
 *         name: longitude
 *         schema:
 *           type: number
 *         required: true
 *         description: Longitude of the user's location
 *       - in: query
 *         name: radius
 *         schema:
 *           type: number
 *           default: 3
 *         required: false
 *         description: Radius in kilometers (default is 3 km)
 *     responses:
 *       200:
 *         description: A list of ads within the specified radius
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/Ad'
 *       400:
 *         description: Missing or invalid parameters
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 error:
 *                   type: string
 *       500:
 *         description: Internal server error
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 error:
 *                   type: string
 */
export const adsNearby = (req, res) => {
  const { latitude, longitude, radius = 3 } = req.query;

  if (!latitude || !longitude) {
    return res.status(400).json({ error: 'Missing latitude or longitude' });
  }

  // Query to find ads within the radius
  const query = `
    SELECT ad.*, partner.name AS partnerName, partner.activity AS partnerActivity, partner.latitude as latitude, partner.longitude as longitude
    FROM ad
    INNER JOIN partner ON ad.partner = partner.id
    WHERE ST_Distance_Sphere(
      point(partner.longitude, partner.latitude),
      point(?, ?)
    ) <= ? * 1000
    AND ad.start <= NOW() AND ad.end >= NOW()
  `;

  db.query(query, [longitude, latitude, radius], (err, results) => {
    if (err) {
      console.error('Error fetching nearby ads:', err);
      return res.status(500).json({ error: 'Internal server error' });
    }
    res.json(results);
  });
};


/**
 * @swagger
 * /ad/all:
 *   get:
 *     summary: Get all ads
 *     tags: [Ad]
 *     responses:
 *       200:
 *         description: A list of ads
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/Ad'
 */
export const allAds = (req, res) => {
  const query = 'SELECT * FROM ad';
  db.query(query, (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results);
  });
};

/**
 * @swagger
 * /ad/byId/{id}:
 *   get:
 *     summary: Get ad by ID
 *     tags: [Ad]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Ad ID
 *     responses:
 *       200:
 *         description: Ad retrieved successfully
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Ad'
 */
export const adById = (req, res) => {
  const query = 'SELECT * FROM ad WHERE id = ?';
  db.query(query, [req.params.id], (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results[0]);
  });
};

/**
 * @swagger
 * /ad/create:
 *   post:
 *     summary: Create a new ad
 *     tags: [Ad]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/Ad'
 *           example:
 *             partner: 1
 *             start: "2024-01-01 00:00:00"
 *             end: "2024-01-31 23:59:59"
 *             offer: 10.5
 *             adtype: 2
 *     responses:
 *       201:
 *         description: Ad created successfully
 */
export const createAd = (req, res) => {
  const query = 'INSERT INTO ad SET ?';
  db.query(query, req.body, (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.status(201).json({ id: result.insertId, ...req.body });
  });
};

/**
 * @swagger
 * /ad/update/{id}:
 *   put:
 *     summary: Update an existing ad
 *     tags: [Ad]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Ad ID
 *         url: file name
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/Ad'
 *           example:
 *             partner: 1
 *             start: "2024-02-01 00:00:00"
 *             end: "2024-02-28 23:59:59"
 *             offer: 15.0
 *             adtype: 3
 *             url: "http://localhost:8080/filename"
 *     responses:
 *       200:
 *         description: Ad updated successfully
 */
export const updateAd = (req, res) => {
  const query = 'UPDATE ad SET ? WHERE id = ?';
  db.query(query, [req.body, req.params.id], (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.json({ message: 'Ad updated successfully' });
  });
};

/**
 * @swagger
 * /ad/delete/{id}:
 *   delete:
 *     summary: Delete ad by ID
 *     tags: [Ad]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Ad ID
 *     responses:
 *       200:
 *         description: Ad deleted successfully
 */
export const deleteAd = (req, res) => {
  const query = 'DELETE FROM ad WHERE id = ?';
  db.query(query, [req.params.id], (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.json({ message: 'Ad deleted successfully' });
  });
};

// **********
// PARTNER ROUTES
// **********

// GET //

/**
 * @swagger
 * /partner/all:
 *   get:
 *     summary: Get all partners
 *     tags: [Partner]
 *     responses:
 *       200:
 *         description: A list of partners
 *         content:
 *           application/json:
 *             schema:
 *               type: array
 *               items:
 *                 $ref: '#/components/schemas/Partner'
 */
export const allPartners = (req, res) => {
  const query = 'SELECT * FROM partner';
  db.query(query, (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results);
  });
};

/**
 * @swagger
 * /partner/byId/{id}:
 *   get:
 *     summary: Get partner by ID
 *     tags: [Partner]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Partner ID
 *     responses:
 *       200:
 *         description: Partner retrieved successfully
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Partner'
 */
export const partnerById = (req, res) => {
  const query = 'SELECT * FROM partner WHERE id = ?';
  db.query(query, [req.params.id], (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results[0]);
  });
};

/**
 * @swagger
 * /partner/byEmail/{email}:
 *   get:
 *     summary: Get partner by Email
 *     tags: [Partner]
 *     parameters:
 *       - in: path
 *         name: email
 *         required: true
 *         schema:
 *           type: string
 *         description: Partner Email
 *     responses:
 *       200:
 *         description: Partner retrieved successfully
 *         content:
 *           application/json:
 *             schema:
 *               $ref: '#/components/schemas/Partner'
 */
export const partnerByEmail = (req, res) => {
  const query = 'SELECT * FROM partner WHERE email = ?';
  db.query(query, [req.params.email], (err, results) => {
    if (err) return errorHandler(res, err, 500);
    res.json(results[0]);
  });
};

/**
 * @swagger
 * /partner/create:
 *   post:
 *     summary: Create a new partner
 *     tags: [Partner]
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/Partner'
 *           example:
 *             name: "Partner Name"
 *             latitude: 48.8566
 *             longitude: 2.3522
 *             address: "123 Partner St, Paris, France"
 *             phone: 1234567890
 *             activity: "Retail"
 *     responses:
 *       201:
 *         description: Partner created successfully
 */
export const createPartner = (req, res) => {
  const query = 'INSERT INTO partner SET ?';
  db.query(query, req.body, (err, result) => {
      if (err) {
          return errorHandler(res, err, 500);
      }
    
      // Get the inserted partner ID
      const partnerId = result.insertId;
    
      // Retrieve the created user from the database
      const selectQuery = 'SELECT * FROM partner WHERE id = ?';
      db.query(selectQuery, [partnerId], (err, results) => {
          if (err) {
              console.log(err.message);
              return errorHandler(res, err, 500);
          }
        
          // Partner created successfully, send the user object in response
          return res.status(201).json(results[0]);
      });
  });
};

/**
 * @swagger
 * /partner/update/{id}:
 *   put:
 *     summary: Update an existing partner
 *     tags: [Partner]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Partner ID
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/Partner'
 *           example:
 *             name: "Updated Partner Name"
 *             latitude: 48.867
 *             longitude: 2.333
 *             address: "456 Updated St, Paris, France"
 *             phone: 987654321
 *             activity: "Updated Activity"
 *     responses:
 *       200:
 *         description: Partner updated successfully
 */
export const updatePartner = (req, res) => {
  const query = 'UPDATE partner SET ? WHERE id = ?';
  db.query(query, [req.body, req.params.id], (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.json({ message: 'Partner updated successfully' });
  });
};

/**
 * @swagger
 * /partner/delete/{id}:
 *   delete:
 *     summary: Delete partner by ID
 *     tags: [Partner]
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *         description: Partner ID
 *     responses:
 *       200:
 *         description: Partner deleted successfully
 */
export const deletePartner = (req, res) => {
  const query = 'DELETE FROM partner WHERE id = ?';
  db.query(query, [req.params.id], (err, result) => {
    if (err) return errorHandler(res, err, 500);
    res.json({ message: 'Partner deleted successfully' });
  });
};
