const { query, one, limitClause } = require('../lib/db')

/**
 * List treatment records for a user with pagination
 * @param {number} userId
 * @param {Object} opts
 * @param {number} opts.pageSize
 * @param {number} opts.offset
 * @returns {Promise<{records: Array, total: number}>}
 */
async function listByUser(userId, { pageSize, offset }) {
  const total = await query(
    'SELECT COUNT(*) AS total FROM treatment_records WHERE user_id = :user_id',
    { user_id: userId }
  )
  const records = await query(
    'SELECT * FROM treatment_records WHERE user_id = :user_id ORDER BY created_at DESC' + limitClause(pageSize, offset),
    { user_id: userId }
  )
  return { records, total: total[0].total }
}

/**
 * Count treatment records for a user
 * @param {number} userId
 * @returns {Promise<number>}
 */
async function countByUser(userId) {
  const rows = await query(
    'SELECT COUNT(*) AS total FROM treatment_records WHERE user_id = :user_id',
    { user_id: userId }
  )
  return rows[0].total
}

/**
 * Find a treatment record by session ID (optionally scoped to user)
 * @param {string} sessionId
 * @param {number} [userId] - if provided, restrict to this user
 * @returns {Promise<Object|null>}
 */
async function findBySession(sessionId, userId) {
  if (userId !== undefined) {
    return one(
      'SELECT * FROM treatment_records WHERE session_id = :session_id AND user_id = :user_id',
      { session_id: sessionId, user_id: userId }
    )
  }
  return one(
    'SELECT * FROM treatment_records WHERE session_id = :session_id',
    { session_id: sessionId }
  )
}

/**
 * Create or update a treatment record (upsert by session_id)
 * @param {Object} record
 * @param {string} record.session_id
 * @param {string} record.device_id
 * @param {number} record.user_id
 * @param {string|null} record.start_time - MySQL datetime string
 * @param {string|null} record.end_time
 * @param {string} record.regions - comma-separated
 * @param {number} record.total_duration_ms
 * @param {number} record.mode
 * @param {number} record.avg_pd
 * @param {number|null} record.battery
 * @param {number|null} record.temperature
 * @param {number|null} record.wavelength
 * @param {number|null} record.brightness
 * @param {string} record.pd_json - JSON string
 * @returns {Promise<Array>} query result
 */
async function create(record) {
  return query(
    `INSERT INTO treatment_records
     (session_id, device_id, user_id, start_time, end_time, regions, total_duration_ms, mode, avg_pd, battery, temperature, wavelength, brightness, pd_json)
     VALUES (:session_id, :device_id, :user_id, :start_time, :end_time, :regions, :total_duration_ms, :mode, :avg_pd, :battery, :temperature, :wavelength, :brightness, :pd_json)
     ON DUPLICATE KEY UPDATE end_time = VALUES(end_time), total_duration_ms = VALUES(total_duration_ms), avg_pd = VALUES(avg_pd), battery = VALUES(battery), temperature = VALUES(temperature), pd_json = VALUES(pd_json)`,
    record
  )
}

/**
 * Update device battery, temperature, and last_online_at
 * @param {string} deviceId
 * @param {number|null} battery
 * @param {number|null} temperature
 * @returns {Promise<Array>} query result
 */
async function updateDevice(deviceId, battery, temperature) {
  return query(
    'UPDATE devices SET battery = COALESCE(:battery, battery), temperature = COALESCE(:temperature, temperature), last_online_at = NOW() WHERE device_id = :device_id',
    { device_id: deviceId, battery, temperature }
  )
}

/**
 * Admin paginated list of treatment records with user nickname
 * @param {Object} opts
 * @param {string} [opts.keyword] - search by user nickname
 * @param {string} [opts.dateFrom] - start date filter (inclusive)
 * @param {string} [opts.dateTo] - end date filter (inclusive)
 * @param {number} opts.pageSize
 * @param {number} opts.offset
 * @returns {Promise<{records: Array, total: number}>}
 */
async function listAdmin({ keyword, userId, dateFrom, dateTo, pageSize, offset }) {
  const conditions = []
  const params = {}
  if (userId) {
    conditions.push('r.user_id = :user_id')
    params.user_id = userId
  }
  if (keyword) {
    conditions.push('u.nickname LIKE :kw')
    params.kw = '%' + keyword + '%'
  }
  if (dateFrom) {
    conditions.push('r.created_at >= :date_from')
    params.date_from = dateFrom
  }
  if (dateTo) {
    conditions.push('r.created_at <= :date_to')
    params.date_to = dateTo
  }
  const where = conditions.length ? ' WHERE ' + conditions.join(' AND ') : ''
  const total = await query(
    'SELECT COUNT(*) AS total FROM treatment_records r LEFT JOIN users u ON u.user_id = r.user_id' + where,
    params
  )
  const records = await query(
    'SELECT r.*, u.nickname FROM treatment_records r LEFT JOIN users u ON u.user_id = r.user_id' +
    where + ' ORDER BY r.created_at DESC' + limitClause(pageSize, offset),
    params
  )
  return { records, total: total[0].total }
}

/**
 * Count admin treatment records with filters
 * @param {Object} opts
 * @param {string} [opts.keyword]
 * @param {string} [opts.dateFrom]
 * @param {string} [opts.dateTo]
 * @returns {Promise<number>}
 */
async function countAdmin({ keyword, dateFrom, dateTo }) {
  const conditions = []
  const params = {}
  if (keyword) {
    conditions.push('u.nickname LIKE :kw')
    params.kw = '%' + keyword + '%'
  }
  if (dateFrom) {
    conditions.push('r.created_at >= :date_from')
    params.date_from = dateFrom
  }
  if (dateTo) {
    conditions.push('r.created_at <= :date_to')
    params.date_to = dateTo
  }
  const where = conditions.length ? ' WHERE ' + conditions.join(' AND ') : ''
  const rows = await query(
    'SELECT COUNT(*) AS total FROM treatment_records r LEFT JOIN users u ON u.user_id = r.user_id' + where,
    params
  )
  return rows[0].total
}

/**
 * Get treatment stats for a user (count + total duration)
 * @param {number} userId
 * @returns {Promise<{treatment_count: number, total_duration: number}>}
 */
async function getStatsByUser(userId) {
  const row = await one(
    'SELECT COUNT(*) AS treatment_count, COALESCE(SUM(total_duration_ms), 0) AS total_duration FROM treatment_records WHERE user_id = :user_id',
    { user_id: userId }
  )
  return row || { treatment_count: 0, total_duration: 0 }
}

/**
 * Get recent treatments for a user (limit 5)
 * @param {number} userId
 * @returns {Promise<Array>}
 */
async function recentByUser(userId) {
  return query(
    'SELECT * FROM treatment_records WHERE user_id = :user_id ORDER BY created_at DESC LIMIT 5',
    { user_id: userId }
  )
}

module.exports = {
  listByUser,
  countByUser,
  findBySession,
  create,
  updateDevice,
  listAdmin,
  countAdmin,
  getStatsByUser,
  recentByUser
}
