'use strict';
const fs = require('fs');
const moment = require('moment')

async function edit (ctx, next) {
   const transaction = await ctx.fs.dc.orm.transaction();
   try {
      const models = ctx.fs.dc.models;
      const { userId } = ctx.fs.api
      const data = ctx.request.body;

      // 或取其他服务信息
      const nvrData = {
         channelCount: 8,
         port: 8080,
      }

      if (data.id) {
         // 修改
         const storageData = Object.assign({}, data, nvrData)
         await models.Nvr.update(storageData, {
            where: {
               id: data.id
            },
            transaction
         })
      } else {
         // 添加
         const storageData = Object.assign({}, data, nvrData, {
            createTime: moment().format(),
            createUserId: userId,
            delete: false,
         })
         await models.Nvr.create(storageData, { transaction })
      }

      await transaction.commit();
      ctx.status = 204;
   } catch (error) {
      await transaction.rollback();
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {}
   }
}

async function get (ctx) {
   try {
      const models = ctx.fs.dc.models;
      const { userId, token } = ctx.fs.api
      const { limit, page, orderBy, orderDirection, keyword, venderId } = ctx.query
      let findOption = {
         attributes: { exclude: ['delete'] },
         where: {
            createUserId: userId,
            delete: false,
         },
         order: [
            [orderBy || 'id', orderDirection || 'DESC']
         ]
      }
      if (limit) {
         findOption.limit = limit
      }
      if (page && limit) {
         findOption.offset = page * limit
      }
      if (keyword) {
         findOption.where.name = { $like: `%${keyword}%` }
      }
      if (venderId) {
         findOption.where.venderId = venderId
      }

      const nvrRes = await models.Nvr.findAll(findOption)
      const total = await models.Nvr.count({
         where: findOption.where
      })

      const nvrIds = nvrRes.map(r => r.id)
      const cameraRes = await models.Camera.findAll({
         where: {
            nvrId: { $in: nvrIds }
         }
      })
      let createUserIds = new Set()
      let cameraIds = []
      for (let c of cameraRes) {
         cameraIds.push(c.id)
         createUserIds.add(c.createUserId)
      }

      // 查在安心云绑定的数据
      const axbindCameraRes = cameraIds.length ?
         await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
         : []

      // 查用户信息
      const createUserRes = await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, { query: { token } })

      for (let { dataValues: n } of nvrRes) {
         const corCameras = cameraRes.filter(c => c.nvrId == n.id)
         const corBind = axbindCameraRes.filter(b => corCameras.some(c => c.id == b.cameraId))
         const corCreateUser = createUserRes.find(u => u.id == n.createUserId)

         n.createUser = {
            name: corCreateUser ? corCreateUser.username : ''
         }
         if (corBind.length) {
            n.station = []
            for (let c of corBind) {
               n.station = n.station.concat(c.stations)
            }
         } else {
            n.station = []
         }
      }

      ctx.status = 200;
      ctx.body = {
         total: total,
         data: nvrRes
      }
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {}
   }
}

async function del (ctx, next) {
   const transaction = await ctx.fs.dc.orm.transaction();
   try {
      const models = ctx.fs.dc.models;
      const { userId, token } = ctx.fs.api
      const { nvrId } = ctx.params

      await models.Nvr.destroy({
         where: {
            id: nvrId
         },
         transaction
      })

      const cameraRes = await models.Camera.findAll({
         where: {
            nvrId
         }
      })

      const cameraIds = cameraRes.map(c => c.id)

      await models.Camera.destroy({
         where: {
            nvrId,
         }
      })
      if (cameraIds.length) {
         await ctx.app.fs.axyRequest.delete('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
      }

      await transaction.commit();
      ctx.status = 204;
   } catch (error) {
      await transaction.rollback();
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {}
   }
}

async function detail (ctx) {
   let errMsg = '获取 NVR 详情失败'
   try {
      const models = ctx.fs.dc.models;
      const { userId, token } = ctx.fs.api
      const { nvrId } = ctx.params

      const nvrRes = await models.Nvr.findOne({
         attributes: { exclude: ['delete'] },
         where: {
            id: nvrId
         },
         include: [{
            model: models.Vender
         }]
      })

      if (!nvrRes) {
         throw errMsg
      }

      // 查询对应的后端服务相关信息

      const cameraRes = await models.Camera.findAll({
         attributes: ['id', 'name', 'channelName', 'serialNo', 'rtmp'],
         where: {
            nvrId
         }
      })
      let cameras = []
      let cameraIds = []
      for (let c of cameraRes) {
         cameraIds.push(c.id)
         cameras.push(c.dataValues)
      }

      const cameraProject = await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
      const bindStations = []
      for (let c of cameraProject) {
         for (let s of c.stations) {
            bindStations.push(s)
         }
      }

      const corUser = await ctx.app.fs.authRequest.get(`user/${nvrRes.createUserId}/message`, { query: { token } })

      let nvrDetail = {
         ...nvrRes.dataValues,
         station: bindStations,
         camera: cameras,
         createUser: {
            namePresent: corUser[0].namePresent
         },
         accessWay: 'GB/T28181'
      }

      ctx.status = 200;
      ctx.body = nvrDetail
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = { message: errMsg }
   }
}

async function nvrExport (ctx) {
   try {
      const { models } = ctx.fs.dc
      const { userId, token } = ctx.fs.api
      const { utils: { simpleExcelDown } } = ctx.app.fs

      const header = [{
         title: "设备名称",
         key: "name",
      }, {
         title: "SIP地址",
         key: "sip",
      }, {
         title: "设备厂家",
         key: "vender",
      }, {
         title: "添加账号",
         key: "createUser",
      }, {
         title: "通道数",
         key: "channelCount",
      }, {
         title: "端口",
         key: "port",
      }, {
         title: "设备状态",
         key: "state",
      }, {
         title: "创建时间",
         key: "createTime",
      }, {
         title: "项目名称",
         key: "projectName",
      }, {
         title: "pcode",
         key: "pcode",
      }, {
         title: "结构物",
         key: "structure",
      },];

      const nvrRes = await models.Nvr.findAll({
         where: {
            createUserId: userId,
         },
         include: [{
            model: models.Vender
         }]
      })
      const nvrIds = nvrRes.map(r => r.id)
      const cameraRes = await models.Camera.findAll({
         where: {
            nvrId: { $in: nvrIds }
         }
      })
      let createUserIds = new Set()
      let cameraIds = []
      for (let c of cameraRes) {
         cameraIds.push(c.id)
         createUserIds.add(c.createUserId)
      }

      // 查在安心云绑定的数据
      const axbindCameraRes =
         cameraIds.length ?
            await ctx.app.fs.axyRequest.get('vcmp/camera/project', { query: { token, cameraId: cameraIds.join(',') } })
            : []

      // 查用户信息
      const createUserRes = await ctx.app.fs.authRequest.get(`user/${[...createUserIds].join(',') || -1}/message`, { query: { token } })

      let exportData = []
      for (let { dataValues: n } of nvrRes) {
         const corCameras = cameraRes.filter(c => c.nvrId == n.id)
         const corBind = axbindCameraRes.filter(b => corCameras.some(c => c.id == b.cameraId))
         const corCreateUser = createUserRes.find(u => u.id == n.createUserId)

         n.createUser = {
            name: corCreateUser ? corCreateUser.username : ''
         }

         n.vender = n.vender ? n.vender.name : ''
         n.createTime = moment(n.createTime).format('YYYY-MM-DD HH:mm:ss')

         let projectName = new Set(),
            pcode = new Set(),
            structure = new Set();
         if (corBind.length) {
            for (let c of corBind) {
               for (let station of c.stations) {
                  structure.add(station.structure.name)
                  for (let project of station.structure.projects) {
                     projectName.add(project.name)
                     pcode.add(project.url)
                  }
               }
            }
         }
         n.projectName = [...projectName].join('\r\n')
         n.pcode = [...pcode].join('\r\n')
         n.structure = [...structure].join('\r\n')

         exportData.push(n)
      }

      const filePath = await simpleExcelDown({ data: exportData, header, fileName: `NVR信息列表_${userId}_${moment().format('YYYYMMDDHHmmss')}` })
      const fileData = fs.readFileSync(filePath);
      let fileName = filePath.split('/').pop()
      ctx.status = 200;
      ctx.set('Content-Type', 'application/x-xls');
      ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
      ctx.body = fileData;
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {}
   }
}

module.exports = {
   edit,
   get,
   del,
   detail,
   nvrExport,
};