const db = require('../config/db');
const logger = require('../utils/logger');
const { logAuditFromReq } = require('../middlewares/audit');

// ── POST /api/sessions/start ──
// Create a new session record on login (called from auth controller)
exports.startSession = async (userId, ipAddress = null, deviceInfo = null) => {
  try {
    // End any stale active sessions for this user
    await db.query(
      `UPDATE user_sessions
       SET status = 'expired',
           logout_at = NOW(),
           duration_mins = TIMESTAMPDIFF(MINUTE, login_at, NOW())
       WHERE user_id = ? AND status = 'active'`,
      [userId]
    );

    const [result] = await db.query(
      `INSERT INTO user_sessions (user_id, ip_address, device_info, status)
       VALUES (?, ?, ?, 'active')`,
      [userId, ipAddress, deviceInfo]
    );
    return result.insertId;
  } catch (err) {
    logger.error('Session start error:', err.message);
    return null;
  }
};

// ── POST /api/sessions/end ──
// End the current session (called on logout)
exports.endSession = async (req, res, next) => {
  try {
    const userId = req.user.id;

    const [result] = await db.query(
      `UPDATE user_sessions
       SET status = 'ended',
           logout_at = NOW(),
           duration_mins = TIMESTAMPDIFF(MINUTE, login_at, NOW())
       WHERE user_id = ? AND status = 'active'
       ORDER BY login_at DESC
       LIMIT 1`,
      [userId]
    );

    res.json({
      message: 'Session ended',
      updated: result.affectedRows,
    });
  } catch (err) {
    next(err);
  }
};

// ── POST /api/sessions/force-end ──
// Admin-only: end a specific session and revoke refresh tokens for that user
exports.forceEndSession = async (req, res, next) => {
  try {
    const { session_id } = req.body;

    const [rows] = await db.query(
      'SELECT id, user_id FROM user_sessions WHERE id = ?',
      [session_id]
    );
    if (rows.length === 0) {
      return res.status(404).json({ error: 'Session not found' });
    }

    const userId = rows[0].user_id;
    await db.query(
      `UPDATE user_sessions
       SET status = 'ended',
           logout_at = NOW(),
           duration_mins = TIMESTAMPDIFF(MINUTE, login_at, NOW())
       WHERE id = ?`,
      [session_id]
    );

    await db.query(
      `UPDATE refresh_tokens
       SET revoked_at = NOW()
       WHERE user_id = ? AND revoked_at IS NULL`,
      [userId]
    );

    logAuditFromReq(req, 'force_logout', 'session', session_id, {
      target_user_id: userId,
    });

    res.json({ message: 'Session ended', session_id });
  } catch (err) {
    next(err);
  }
};

// ── GET /api/sessions/active ──
// List all currently active sessions
exports.getActiveSessions = async (req, res, next) => {
  try {
    const [rows] = await db.query(
      `SELECT us.*, u.username, u.full_name, u.role, u.avatar_url,
              TIMESTAMPDIFF(MINUTE, us.login_at, NOW()) AS active_mins
       FROM user_sessions us
       JOIN users u ON u.id = us.user_id
       WHERE us.status = 'active'
       ORDER BY us.login_at DESC`
    );
    res.json(rows);
  } catch (err) {
    next(err);
  }
};

// ── GET /api/sessions/history ──
// Query params: user_id, from_date, to_date, page, limit
exports.getSessionHistory = async (req, res, next) => {
  try {
    const { user_id, from_date, to_date, page = 1, limit = 50 } = req.query;

    const conditions = [];
    const params = [];

    if (user_id) {
      conditions.push('us.user_id = ?');
      params.push(parseInt(user_id, 10));
    }
    if (from_date) {
      conditions.push('us.login_at >= ?');
      params.push(from_date);
    }
    if (to_date) {
      conditions.push('us.login_at <= ?');
      params.push(to_date + ' 23:59:59');
    }

    const where = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
    const offset = (parseInt(page, 10) - 1) * parseInt(limit, 10);

    const [countRows] = await db.query(
      `SELECT COUNT(*) AS total FROM user_sessions us ${where}`,
      params
    );

    const [rows] = await db.query(
      `SELECT us.*, u.username, u.full_name, u.role, u.avatar_url
       FROM user_sessions us
       JOIN users u ON u.id = us.user_id
       ${where}
       ORDER BY us.login_at DESC
       LIMIT ? OFFSET ?`,
      [...params, parseInt(limit, 10), offset]
    );

    res.json({
      data: rows,
      pagination: {
        page: parseInt(page, 10),
        limit: parseInt(limit, 10),
        total: countRows[0].total,
        pages: Math.ceil(countRows[0].total / parseInt(limit, 10)),
      },
    });
  } catch (err) {
    next(err);
  }
};

// ── GET /api/sessions/attendance ──
// Staff attendance/session report grouped by user and date
// Query params: from_date, to_date, user_id
exports.getAttendanceReport = async (req, res, next) => {
  try {
    const { from_date, to_date, user_id } = req.query;

    const conditions = [];
    const params = [];

    if (user_id) {
      conditions.push('us.user_id = ?');
      params.push(parseInt(user_id, 10));
    }
    if (from_date) {
      conditions.push('DATE(us.login_at) >= ?');
      params.push(from_date);
    }
    if (to_date) {
      conditions.push('DATE(us.login_at) <= ?');
      params.push(to_date);
    }

    const where = conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';

    // Daily attendance per user
    const [dailyRows] = await db.query(
      `SELECT
         us.user_id,
         u.full_name,
         u.username,
         u.role,
         DATE(us.login_at) AS date,
         COUNT(*) AS session_count,
         MIN(us.login_at) AS first_login,
         MAX(COALESCE(us.logout_at, NOW())) AS last_activity,
         SUM(COALESCE(us.duration_mins, TIMESTAMPDIFF(MINUTE, us.login_at, COALESCE(us.logout_at, NOW())))) AS total_mins
       FROM user_sessions us
       JOIN users u ON u.id = us.user_id
       ${where}
       GROUP BY us.user_id, u.full_name, u.username, u.role, DATE(us.login_at)
       ORDER BY DATE(us.login_at) DESC, u.full_name ASC`,
      params
    );

    // User summary
    const [summaryRows] = await db.query(
      `SELECT
         us.user_id,
         u.full_name,
         u.username,
         u.role,
         COUNT(*) AS total_sessions,
         COUNT(DISTINCT DATE(us.login_at)) AS days_active,
         SUM(COALESCE(us.duration_mins, TIMESTAMPDIFF(MINUTE, us.login_at, COALESCE(us.logout_at, NOW())))) AS total_mins,
         ROUND(AVG(COALESCE(us.duration_mins, TIMESTAMPDIFF(MINUTE, us.login_at, COALESCE(us.logout_at, NOW())))), 0) AS avg_session_mins
       FROM user_sessions us
       JOIN users u ON u.id = us.user_id
       ${where}
       GROUP BY us.user_id, u.full_name, u.username, u.role
       ORDER BY total_mins DESC`,
      params
    );

    res.json({
      daily: dailyRows,
      summary: summaryRows,
    });
  } catch (err) {
    next(err);
  }
};
