'use strict';

const moment = require('moment')
const { alarmConfirmLog } = require('./alarmConfirmLog');
async function inspection(ctx) {
   // 巡查
   try {
      const models = ctx.fs.dc.models;
      const { projectAppId, screenshot = [], } = ctx.request.body

      const now = moment().format()
      const storageData = screenshot.map(s => {
         return {
            projectAppId,
            screenshot: s.url,
            createTime: now,
            description: s.description,
            router: s.router
         }
      })

      await models.AppInspection.bulkCreate(storageData)

      ctx.status = 204;
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {
         message: typeof error == 'string' ? error : undefined
      }
   }
}

async function inspectionList(ctx) {
   try {
      const models = ctx.fs.dc.models;
      const { clickHouse } = ctx.app.fs
      const { utils: { anxinStrucIdRange, pomsProjectRange } } = ctx.app.fs
      const { pepProjectId, timeStart, timeEnd, projectId, appId, noted } = ctx.query

      let pomsProjectIds = null
      if (!projectId && !appId) {
         let pomsProject = await pomsProjectRange({
            ctx, pepProjectId
         })
         pomsProjectIds = pomsProject.map(p => p.id)
      }

      let findOption = {
         where: {

         },
         order: [['id', 'DESC']],
         include: [{
            model: models.App,
            required: true,
            where: appId ? {
               id: appId
            } : undefined,
            include: {
               model: models.ProjectCorrelation,
               required: true,
               where: Object.assign({},
                  {
                     del: false
                  },
                  projectId ?
                     {
                        id: projectId
                     } : {},
                  pomsProjectIds ? {
                     id: { $in: pomsProjectIds }
                  } : {}
               ),
               attributes: {
                  exclude: ['anxinProjectId', 'createTime', 'createUser']
               }
            }
         }]
      }
      // if (timeStart && timeEnd) {
      //    findOption.where.createTime = { $between: [moment(timeStart).format(), moment(timeEnd).format()] }
      // }
      if (noted) {
         if (noted == 'noted') {
            findOption.where.notedTime = { $ne: null }
         } else if (noted == 'unnote') {
            findOption.where.notedTime = null
         }
      }

      const inspectionRes = await models.AppInspection.findAll(findOption)
      let notedUserIds = new Set()
      for (let ins of inspectionRes) {
         if (ins.notedPepUserId) {
            notedUserIds.add(ins.notedPepUserId)
         }
      }
      let userPepRes = notedUserIds.size ?
         await clickHouse.pepEmis.query(`SELECT DISTINCT user.id AS id, "user"."name" AS name FROM user WHERE user.id IN (${[...notedUserIds].join(',')})`).toPromise() :
         []
      for (let ins of inspectionRes) {
         if (ins.notedPepUserId) {
            const corUser = userPepRes.find(up => up.id == ins.notedPepUserId)
            ins.dataValues.notedPepUser = corUser ? corUser.name : ''
         }
      }
      ctx.status = 200;
      ctx.body = inspectionRes
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {
         message: typeof error == 'string' ? error : undefined
      }
   }
}

async function notedInspection(ctx) {
   try {
      const models = ctx.fs.dc.models;
      const { inspectionId } = ctx.request.body
      const { userId, pepUserId } = ctx.fs.api

      await models.AppInspection.update({
         notedPepUserId: pepUserId,
         notedTime: moment().format()
      }, {
         where: {
            id: inspectionId
         }
      })

      ctx.status = 204;
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {
         message: typeof error == 'string' ? error : undefined
      }
   }
}

async function apiError(ctx) {
   try {
      const models = ctx.fs.dc.models;
      const { projectAppId, alarmContent, router, statusCode, screenshot = '', type } = ctx.request.body
      const now = moment().format()

      if (!type) {
         throw '请标明告警类型 type'
      }

      const isRestore = statusCode == 200 || statusCode == 204
      if (isRestore) {
         const existRes = await models.AppAlarm.findAll({
            where: {
               projectAppId, router, alarmContent,
               confirmTime: null, type
            }
         })
         if (existRes.length) {
            await models.AppAlarm.update({
               updateTime: now,
               confirmTime: now,
               confirmAuto: true,
            }, {
               where: {
                  id: { $in: existRes.map(e => e.id) }
               }
            })
         }
      } else {
         let storageData = {
            projectAppId, alarmContent, router, statusCode, type
         }
         const existRes = await models.AppAlarm.findOne({
            where: {
               projectAppId, alarmContent, router, statusCode,
               confirmTime: null, type,
            }
         })
         if (existRes) {
            await models.AppAlarm.update({
               updateTime: now
            }, {
               where: {
                  id: existRes.id
               }
            })
         } else {
            const existCount = await models.AppAlarm.count({
               where: {

               }
            })
            storageData.serialNumber = 'WEB' + (existCount < 9 ? '0' + (existCount + 1) : existCount)
            storageData.createTime = now
            storageData.screenshot = screenshot
            await models.AppAlarm.create(storageData)
         }

      }

      ctx.status = 200;
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {
         message: typeof error == 'string' ? error : undefined
      }
   }
}

async function apiErrorList(ctx) {
   try {
      const models = ctx.fs.dc.models;
      const { clickHouse } = ctx.app.fs
      const { utils: { anxinStrucIdRange, pomsProjectRange } } = ctx.app.fs
      const { keyword, errType, confirmState, sustainTimeStart, sustainTimeEnd, limit, page, pepProjectId } = ctx.query

      let pomsProject = await pomsProjectRange({
         ctx, pepProjectId,
         keywordTarget: 'pepProject',
         keyword,
      })
      const pomsProjectIds = pomsProject.map(p => p.id)
      let findOption = {
         where: {
            $or: []
         },
         include: [{
            model: models.App,
            where: {

            },
            attributes: {
               exclude: ['projectId']
            },
            include: [{
               model: models.ProjectCorrelation,
               where: {

               },
               attributes: {
                  exclude: ['createTime', 'createUser', 'anxinProjectId',]
               },
            }]
         }]
      }
      if (keyword) {
         findOption.where.$or.push(
            {
               '$app->projectCorrelations.id$': {
                  $in: pomsProjectIds
               },
            }
         )
         findOption.where.$or.push(
            {
               '$app.name$': { $like: `%${keyword}%` }
            }
         )
      } else {
         findOption.where['$app->projectCorrelations.id$'] = {
            $in: pomsProjectIds
         }
      }

      if (errType) {
         findOption.where.type = errType // element / apiError
      }
      if (confirmState) {
         if (confirmState == 'confirmd') {
            findOption.where.confirmTime = { $ne: null }
         } else if (confirmState == 'unconfirmed') {
            findOption.where.confirmTime = null
         }
      }
      if (sustainTimeStart && sustainTimeEnd) {
         findOption.where.$or = findOption.where.$or.concat([
            {
               createTime: { $between: [moment(sustainTimeStart).format(), moment(sustainTimeEnd).format()] },
            },
            {
               updateTime: { $between: [moment(sustainTimeStart).format(), moment(sustainTimeEnd).format()] }
            },
            {
               createTime: { $lte: moment(sustainTimeStart).format() },
               updateTime: { $gte: moment(sustainTimeEnd).format() },
            }
         ])
      }
      if (limit) {
         findOption.limit = limit
      }
      if (page && limit) {
         findOption.offset = page * limit
      }
      if (!findOption.where.$or.length) {
         delete findOption.where.$or
      }
      const listRes = await models.AppAlarm.findAndCountAll(findOption)

      for (let lr of listRes.rows) {
         if (lr.app && lr.app.projectCorrelations) {
            for (let p of lr.app.projectCorrelations) {
               let corProjectCorrelations = pomsProject.find(pr => pr.id == p.id)
               if (corProjectCorrelations) {
                  p.dataValues = corProjectCorrelations
               }
            }
         }
      }

      ctx.status = 200;
      ctx.body = listRes
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {
         message: typeof error == 'string' ? error : undefined
      }
   }
}

async function confirmApiError(ctx) {
   try {
      const models = ctx.fs.dc.models;
      const { confirm, appAlarmId = [], confirmPost } = ctx.request.body
      await models.AppAlarm.update({
         confirm,
         confirmTime: moment().format()
      }, {
         where: {
            id: { $in: appAlarmId }
         }
      })

      await alarmConfirmLog(ctx, confirmPost, confirm);//告警确认日志

      ctx.status = 204;
   } catch (error) {
      ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
      ctx.status = 400;
      ctx.body = {
         message: typeof error == 'string' ? error : undefined
      }
   }
}

module.exports = {
   inspection,
   inspectionList,
   notedInspection,
   apiError,
   apiErrorList,
   confirmApiError,
};