const express = require('express')
const router = express.Router()
const db = require('qmi-cloud-common/mongo');
const azurecli = require('qmi-cloud-common/azurecli');
const passport = require('../passport');
const fs = require('fs-extra');


/**
 * @swagger
 * /provisions:
 *    get:
 *      description: Get all Provisions
 *      summary: Get all Provisions)
 *      tags:
 *        - admin
 *      produces:
 *        - application/json
 *      parameters:
 *        - name: filter
 *          in: query
 *          required: false
 *          type: object
 *          content:
 *            application/json: 
 *              schema:
 *                type: object
 *        - name: populates
 *          in: query
 *          required: false
 *          type: array
  *        - name: select
 *          in: query
 *          required: false
 *          type: string
 *        - name: page
 *          in: query
 *          required: false
 *          type: integer
 *        - name: size
 *          in: query
 *          required: false
 *          type: integer
 *      responses:
 *        200:
 *          description: JSON Array
 */
router.get('/', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {
  

  try {  
    let filter = req.query.filter? JSON.parse(req.query.filter) : {};
    if ( filter.isDeleted === undefined ) {
      filter.isDeleted = false;
    }
    var page;
    if ( req.query.page && req.query.size ) {
      page = {
        page: parseInt(req.query.page), 
        size: parseInt(req.query.size)
      }
    }
    const result = await db.provision.getPage(filter, page, req.query.populates, req.query.select);

    if (result.next){
      result.nextUrl = new URL(req.protocol + '://' + req.get('Host') + req.baseUrl);
      if ( req.query.filter ) {
        result.nextUrl.searchParams.append("filter", req.query.filter); 
      }
      if ( req.query.populates ) {
        result.nextUrl.searchParams.append("populates", req.query.populates);
      }
      if ( req.query.select ) {
        result.nextUrl.searchParams.append("select", req.query.select);
      }
      result.nextUrl.searchParams.append("page", result.next.page);
      result.nextUrl.searchParams.append("size", result.next.size);
    }
    
    return res.json(result);
  } catch (error) {
    next(error);
  }
});

/**
 * @swagger
 * /provisions/vmImagesLogs:
 *    get:
 *      description: Get all vmImages
 *      summary: Get all vmImages
 *      produces:
 *        - application/json
 *      parameters:
 *        - name: filter
 *          in: query
 *          required: false
 *          type: object
 *          content:
 *            application/json: 
 *              schema:
 *                type: object
 *        - name: skip
 *          in: query
 *          required: false
 *          type: integer
 *        - name: limit
 *          in: query
 *          required: false
 *          type: integer
 *      responses:
 *        200:
 *          description: JSON Array
 */
router.get('/vmImagesLogs', passport.ensureAuthenticated, async (req, res, next) => {
  try { 

    let filter = req.query.filter? JSON.parse(req.query.filter) : {}; 
    filter.isDeleted = {"$exists": true};
    let select = "_id vmImage"
    let populates = "[]";

    const result = await db.provision.get(filter, select, req.query.skip, req.query.limit, populates);
    var final = [];
    result.results.forEach(p=>{
      for( let key in p.vmImage ) {
          var o = {
            "_id": p._id.toString(),
            "vmIndex": key,
            "vmType": p.vmImage[key].vmType? p.vmImage[key].vmType : null,
            "diskSizeGb": p.vmImage[key].diskSizeGb? p.vmImage[key].diskSizeGb : null,
            "versionProduct": p.vmImage[key].version? p.vmImage[key].version.name : null,
            "versionImage": p.vmImage[key].version? p.vmImage[key].version.image : null
          }
          final.push(o);
      }    
    })
    var out = {
      total: result.total,
      count: result.count
    };
    if ( result.nextSkip && result.nextLimit ) {
      out.nextUrl = new URL(req.protocol + '://' + req.get('Host') + req.baseUrl);
      if ( req.query.filter ) {
        out.nextUrl.searchParams.append("filter", req.query.filter);
      }
      if ( req.query.populates ) {
        out.nextUrl.searchParams.append("populates", req.query.populates);
      }
      out.nextUrl.searchParams.append("skip", result.nextSkip);
      out.nextUrl.searchParams.append("limit", result.nextLimit);
    }
    out.results = final;

    return res.json(out);
  } catch (error) {
    next(error);
  }
});

/**
 * @swagger
 * /provisions/{id}:
 *    get:
 *      description: Get Provision by ID
 *      summary: Get a Terraform Provision details by ID
 *      tags:
 *        - admin
 *      produces:
 *        - application/json
 *      parameters:
 *        - name: id
 *          in: path
 *          type: string
 *          required: true
 *      responses:
 *        200:
 *          description: Provision
 *        404:
 *          description: Not found
 *        
 */
router.get('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {
  try {
    const mongoJob = await db.provision.getById(req.params.id);
    if (!mongoJob){
      return res.status(404).json({"msg": "Not found"});
    }
    return res.json(mongoJob);
  } catch (error) {
    next(error);
  }
});


/**
 * @swagger
 * /provisions/{id}:
 *    delete:
 *      description: Delete Provision by ID
 *      summary: Delete a Terraform Provision by ID
 *      tags:
 *        - admin
 *      produces:
 *        - application/json
 *      parameters:
 *        - name: id
 *          in: path
 *          type: string
 *          required: true
 *      responses:
 *        200:
 *          description: Provision
 *        404:
 *          description: Not found
 *        
 */
router.delete('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {
  try {
    const mongoJob = await db.provision.getById(req.params.id);
    if (!mongoJob){
      return res.status(404).json({"msg": "Not found"});
    }
    const toDestroy = await db.destroy.get({"provId": req.params.id});
    const delDest = await db.destroy.del(toDestroy[0]._id.toString());
    const delProv = await db.provision.del(req.params.id);

    //Move folder 
    fs.moveSync(`/provisions/${mongoJob.scenario}_${req.params.id}`, `/provisions/deleted/${mongoJob.scenario}_${req.params.id}`, { overwrite: true })

    return res.json({"provision": delProv, "destroy": delDest});
  } catch (error) {
    next(error);
  }
});

/**
 * @swagger
 * /provisions/{id}:
 *    put:
 *      description: Update Provision by ID
 *      summary: Update Provision by ID
 *      tags:
 *        - admin
 *      parameters:
 *        - name: id
 *          in: path
 *          type: string
 *          required: true
 *        - in: body
 *          name: body
 *          description: Provision object
 *          required: true
 *      produces:
 *        - application/json
 *      responses:
 *        200:
 *          description: Provision
 */
router.put('/:id', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {

  try {
    const result = await db.provision.update(req.params.id, req.body);
    return res.json(result);
  } catch (error) {
    next(error);
  }
});

/**
 * @swagger
 * /provisions/{id}/logs:
 *    get:
 *      description: Get Logs for Provision by ID
 *      summary: Get Logs for a Provision by ID
 *      produces:
 *        - text/plain
 *      parameters:
 *        - name: id
 *          in: path
 *          type: string
 *          required: true
 *      responses:
 *        200:
 *          description: Log file
 *        404:
 *          description: Not found
 */
router.get('/:id/logs', passport.ensureAuthenticated, async (req, res, next) => {
  try {
    const mongoJob = await db.provision.getById(req.params.id);
    if (!mongoJob){
      return res.status(404).json({"msg": "Not found"});
    }
    return res.sendFile(mongoJob.logFile);
  } catch (error) {
    next(error);
  }
});

/**
 * @swagger
 * /provisions/{id}/updatetagsvms:
 *    post:
 *      description: Update Tags in VMs for this provision
 *      summary: Update Tags in VMs for this provision
 *      tags:
 *        - admin
 *      produces:
 *        - application/json
 *      parameters:
 *        - name: id
 *          in: path
 *          type: string
 *          required: true
 *      requestBody:
 *        required: true
 *        content:
 *          application/json:
 *            schema:
 *              type: object
 *      responses:
 *        200:
 *          description: Provision
 *        404:
 *          description: Not found
 *        
 */
router.post('/:id/updatetagsvms', passport.ensureAuthenticatedAndAdmin, async (req, res, next) => {
  try {

    let tagsEdit = req.body;
    if ( !tagsEdit ) {
      return res.json({"msg": "No tags to be updated", "success": false});
    }

    let provision = await db.provision.getById(req.params.id);
    if (!provision) {
      return res.status(404).json({"msg": "Not found provision with id: "+req.params.id, "success": false});
    }
    var result = await cli.updateVmsTags(provision._id, tagsEdit);
    return res.json({"msg": "Tags are being updated", "result": result, "success": true});

  } catch (error) {
    next(error);
  }
});



module.exports = router;