/**
 * 操作日志控制器
 * @file operationLogController.js
 * @description 处理操作日志相关的API请求
 */
const { OperationLog, User } = require('../models');
const { validationResult } = require('express-validator');
const { Op } = require('sequelize');

/**
 * 获取操作日志列表
 * @param {Object} req 请求对象
 * @param {Object} res 响应对象
 */
const getOperationLogs = async (req, res) => {
  try {
    const {
      page = 1,
      pageSize = 20,
      userId,
      username,
      operationType,
      moduleName,
      tableName,
      startDate,
      endDate,
      sortBy = 'created_at',
      sortOrder = 'DESC'
    } = req.query;

    // 构建查询条件
    const whereClause = {};

    if (userId) {
      whereClause.user_id = userId;
    }

    if (username) {
      whereClause.username = {
        [Op.like]: `%${username}%`
      };
    }

    if (operationType) {
      whereClause.operation_type = operationType;
    }

    if (moduleName) {
      whereClause.module_name = {
        [Op.like]: `%${moduleName}%`
      };
    }

    if (tableName) {
      whereClause.table_name = tableName;
    }

    if (startDate && endDate) {
      whereClause.created_at = {
        [Op.between]: [startDate, endDate]
      };
    }

    // 构建排序条件
    const orderClause = [[sortBy, sortOrder.toUpperCase()]];

    // 执行分页查询
    const result = await OperationLog.paginate(
      {
        where: whereClause,
        order: orderClause,
        include: [
          {
            model: User,
            as: 'user',
            attributes: ['id', 'username', 'email', 'roles']
          }
        ]
      },
      parseInt(page),
      parseInt(pageSize)
    );

    res.json({
      success: true,
      data: result.data,
      pagination: result.pagination,
      message: '获取操作日志列表成功'
    });
  } catch (error) {
    console.error('获取操作日志列表失败:', error);
    res.status(500).json({
      success: false,
      message: '获取操作日志列表失败',
      error: error.message
    });
  }
};

/**
 * 获取操作日志详情
 * @param {Object} req 请求对象
 * @param {Object} res 响应对象
 */
const getOperationLogById = async (req, res) => {
  try {
    const { id } = req.params;

    const operationLog = await OperationLog.findByPk(id, {
      include: [
        {
          model: User,
          as: 'user',
          attributes: ['id', 'username', 'email', 'roles']
        }
      ]
    });

    if (!operationLog) {
      return res.status(404).json({
        success: false,
        message: '操作日志不存在'
      });
    }

    res.json({
      success: true,
      data: operationLog,
      message: '获取操作日志详情成功'
    });
  } catch (error) {
    console.error('获取操作日志详情失败:', error);
    res.status(500).json({
      success: false,
      message: '获取操作日志详情失败',
      error: error.message
    });
  }
};

/**
 * 获取操作统计
 * @param {Object} req 请求对象
 * @param {Object} res 响应对象
 */
const getOperationStats = async (req, res) => {
  try {
    const { type, userId, moduleName, startDate, endDate } = req.query;

    let stats = {};

    if (type === 'user' && userId) {
      stats = await OperationLog.getUserOperationStats(userId, startDate, endDate);
    } else if (type === 'module' && moduleName) {
      stats = await OperationLog.getModuleOperationStats(moduleName, startDate, endDate);
    } else {
      // 获取总体统计
      const whereClause = {};
      if (startDate && endDate) {
        whereClause.created_at = {
          [Op.between]: [startDate, endDate]
        };
      }

      const result = await OperationLog.findAll({
        where: whereClause,
        attributes: [
          'operation_type',
          [OperationLog.sequelize.fn('COUNT', OperationLog.sequelize.col('id')), 'count']
        ],
        group: ['operation_type'],
        raw: true
      });

      stats = result.reduce((acc, stat) => {
        acc[stat.operation_type] = parseInt(stat.count);
        return acc;
      }, {});
    }

    res.json({
      success: true,
      data: stats,
      message: '获取操作统计成功'
    });
  } catch (error) {
    console.error('获取操作统计失败:', error);
    res.status(500).json({
      success: false,
      message: '获取操作统计失败',
      error: error.message
    });
  }
};

/**
 * 获取操作日志图表数据
 * @param {Object} req 请求对象
 * @param {Object} res 响应对象
 */
const getOperationChartData = async (req, res) => {
  try {
    const { type = 'daily', startDate, endDate } = req.query;

    let dateFormat, groupBy;
    switch (type) {
      case 'hourly':
        dateFormat = '%Y-%m-%d %H:00:00';
        groupBy = 'DATE_FORMAT(created_at, "%Y-%m-%d %H:00:00")';
        break;
      case 'daily':
        dateFormat = '%Y-%m-%d';
        groupBy = 'DATE(created_at)';
        break;
      case 'monthly':
        dateFormat = '%Y-%m';
        groupBy = 'DATE_FORMAT(created_at, "%Y-%m")';
        break;
      default:
        dateFormat = '%Y-%m-%d';
        groupBy = 'DATE(created_at)';
    }

    const whereClause = {};
    if (startDate && endDate) {
      whereClause.created_at = {
        [Op.between]: [startDate, endDate]
      };
    }

    const result = await OperationLog.findAll({
      where: whereClause,
      attributes: [
        [OperationLog.sequelize.fn('DATE_FORMAT', OperationLog.sequelize.col('created_at'), dateFormat), 'date'],
        'operation_type',
        [OperationLog.sequelize.fn('COUNT', OperationLog.sequelize.col('id')), 'count']
      ],
      group: ['date', 'operation_type'],
      order: [['date', 'ASC']],
      raw: true
    });

    // 处理图表数据
    const chartData = {
      dates: [],
      series: {
        CREATE: [],
        UPDATE: [],
        DELETE: []
      }
    };

    const dateSet = new Set();
    result.forEach(item => {
      dateSet.add(item.date);
    });

    chartData.dates = Array.from(dateSet).sort();

    chartData.dates.forEach(date => {
      const createItem = result.find(item => item.date === date && item.operation_type === 'CREATE');
      const updateItem = result.find(item => item.date === date && item.operation_type === 'UPDATE');
      const deleteItem = result.find(item => item.date === date && item.operation_type === 'DELETE');

      chartData.series.CREATE.push(createItem ? parseInt(createItem.count) : 0);
      chartData.series.UPDATE.push(updateItem ? parseInt(updateItem.count) : 0);
      chartData.series.DELETE.push(deleteItem ? parseInt(deleteItem.count) : 0);
    });

    res.json({
      success: true,
      data: chartData,
      message: '获取操作日志图表数据成功'
    });
  } catch (error) {
    console.error('获取操作日志图表数据失败:', error);
    res.status(500).json({
      success: false,
      message: '获取操作日志图表数据失败',
      error: error.message
    });
  }
};

/**
 * 清理过期日志
 * @param {Object} req 请求对象
 * @param {Object} res 响应对象
 */
const cleanExpiredLogs = async (req, res) => {
  try {
    const { daysToKeep = 90 } = req.body;

    const deletedCount = await OperationLog.cleanExpiredLogs(daysToKeep);

    res.json({
      success: true,
      data: { deletedCount },
      message: `成功清理了 ${deletedCount} 条过期日志`
    });
  } catch (error) {
    console.error('清理过期日志失败:', error);
    res.status(500).json({
      success: false,
      message: '清理过期日志失败',
      error: error.message
    });
  }
};

/**
 * 导出操作日志
 * @param {Object} req 请求对象
 * @param {Object} res 响应对象
 */
const exportOperationLogs = async (req, res) => {
  try {
    const {
      userId,
      username,
      operationType,
      moduleName,
      tableName,
      startDate,
      endDate
    } = req.query;

    // 构建查询条件
    const whereClause = {};

    if (userId) {
      whereClause.user_id = userId;
    }

    if (username) {
      whereClause.username = {
        [Op.like]: `%${username}%`
      };
    }

    if (operationType) {
      whereClause.operation_type = operationType;
    }

    if (moduleName) {
      whereClause.module_name = {
        [Op.like]: `%${moduleName}%`
      };
    }

    if (tableName) {
      whereClause.table_name = tableName;
    }

    if (startDate && endDate) {
      whereClause.created_at = {
        [Op.between]: [startDate, endDate]
      };
    }

    const logs = await OperationLog.findAll({
      where: whereClause,
      order: [['created_at', 'DESC']],
      include: [
        {
          model: User,
          as: 'user',
          attributes: ['id', 'username', 'email', 'roles']
        }
      ]
    });

    // 转换为CSV格式
    const csvHeaders = [
      'ID',
      '操作用户',
      '用户角色',
      '操作类型',
      '模块名称',
      '数据表名',
      '记录ID',
      '操作描述',
      'IP地址',
      '请求URL',
      '请求方法',
      '响应状态',
      '执行时间(ms)',
      '创建时间'
    ];

    const csvRows = logs.map(log => [
      log.id,
      log.username,
      log.user_role,
      log.operation_type,
      log.module_name,
      log.table_name,
      log.record_id || '',
      log.operation_desc,
      log.ip_address || '',
      log.request_url || '',
      log.request_method || '',
      log.response_status || '',
      log.execution_time || '',
      log.created_at
    ]);

    const csvContent = [csvHeaders, ...csvRows]
      .map(row => row.map(field => `"${field}"`).join(','))
      .join('\n');

    res.setHeader('Content-Type', 'text/csv; charset=utf-8');
    res.setHeader('Content-Disposition', 'attachment; filename=operation_logs.csv');
    res.send('\ufeff' + csvContent); // 添加BOM以支持中文
  } catch (error) {
    console.error('导出操作日志失败:', error);
    res.status(500).json({
      success: false,
      message: '导出操作日志失败',
      error: error.message
    });
  }
};

module.exports = {
  getOperationLogs,
  getOperationLogById,
  getOperationStats,
  getOperationChartData,
  cleanExpiredLogs,
  exportOperationLogs
};
