const router = require('express').Router()
const { ok, fail } = require('../lib/response')
const { hashPassword, hashPasswordLegacy, verifyPassword, signAdmin } = require('../lib/auth')
const { requireAdmin } = require('../middleware/auth')
const { invalidateCache } = require('../lib/settings-cache')
const adminDao = require('../dao/admin.dao')
const deviceDao = require('../dao/device.dao')
const bindingDao = require('../dao/binding.dao')
const commandDao = require('../dao/command.dao')
const userDao = require('../dao/user.dao')
const subscriptionDao = require('../dao/subscription.dao')
const treatmentDao = require('../dao/treatment.dao')
const logDao = require('../dao/log.dao')
const settingsDao = require('../dao/settings.dao')

const wrap = fn => (req, res, next) => fn(req, res, next).catch(next)

function pageParams(query) {
  const page = Math.max(1, parseInt(query.page, 10) || 1)
  const pageSize = Math.min(Math.max(1, parseInt(query.page_size, 10) || 20), 100)
  return { page, pageSize, offset: (page - 1) * pageSize }
}

// --- Auth ---

router.post('/login', wrap(async (req, res) => {
  const username = req.body.username || ''
  const password = req.body.password || ''
  const admin = await adminDao.findByUsername(username)
  if (!admin) return res.json(fail(1001, '用户名或密码错误'))
  let matched = verifyPassword(password, admin.password_hash)
  if (!matched) {
    if (admin.password_salt && hashPasswordLegacy(password, admin.password_salt) === admin.password_hash) {
      const newHash = hashPassword(password)
      await adminDao.updatePassword(admin.admin_id, newHash)
      matched = true
    }
  }
  if (!matched) return res.json(fail(1001, '用户名或密码错误'))
  const token = signAdmin(admin)
  await logDao.write({ admin_id: admin.admin_id, action: 'admin_login', detail: '管理员登录: ' + username, ip: req.ip })
  res.json(ok({ token, admin_id: String(admin.admin_id), username: admin.username, real_name: admin.real_name, role: admin.role }))
}))

router.post('/password', requireAdmin, wrap(async (req, res) => {
  const oldPassword = req.body.old_password || ''
  const newPassword = req.body.new_password || ''
  if (newPassword.length < 6) return res.json(fail(2001, 'password too short'))
  const current = await adminDao.findById(req.admin.admin_id)
  if (!current) return res.json(fail(1002, '未授权，请重新登录'))
  let matched = verifyPassword(oldPassword, current.password_hash)
  if (!matched && current.password_salt && hashPasswordLegacy(oldPassword, current.password_salt) === current.password_hash) {
    matched = true
  }
  if (!matched) return res.json(fail(1001, '原密码错误'))
  const newHash = hashPassword(newPassword)
  await adminDao.updatePassword(req.admin.admin_id, newHash)
  await logDao.write({ admin_id: req.admin.admin_id, action: 'admin_change_password', detail: '管理员修改密码', ip: req.ip })
  res.json(ok({ message: 'success' }))
}))

// --- Dashboard ---

router.get('/dashboard', requireAdmin, wrap(async (req, res) => {
  const counts = await adminDao.getDashboardCounts()
  const subStats = await adminDao.getSubscriptionStats()
  res.json(ok({
    device_count: counts.device_count,
    user_count: counts.user_count,
    treatment_count: counts.treatment_count,
    subscription_count: counts.subscription_count,
    sub_stats: subStats
  }))
}))

// --- Devices ---

router.get('/devices', requireAdmin, wrap(async (req, res) => {
  const { page, pageSize, offset } = pageParams(req.query)
  const { records, total } = await deviceDao.list({
    keyword: req.query.keyword,
    pageSize,
    offset
  })
  res.json(ok({ records, total }))
}))

router.post('/devices', requireAdmin, wrap(async (req, res) => {
  const deviceId = String(req.body.device_id || '').trim()
  if (!deviceId) return res.json(fail(2001, 'device_id required'))
  await deviceDao.create({
    device_id: deviceId,
    product_id: req.body.product_id || 'HOX_LIGHT_MASK',
    device_secret: req.body.device_secret || '',
    device_name: req.body.device_name || 'LumiFlow',
    firmware_version: req.body.firmware_version || '1.0.0'
  })
  await logDao.write({ admin_id: req.admin.admin_id, action: 'admin_device_create', detail: '预生成产品码: ' + deviceId, ip: req.ip })
  res.json(ok({ device_id: deviceId }))
}))

router.post('/devices/batch', requireAdmin, wrap(async (req, res) => {
  const deviceIds = req.body.device_ids
  if (!Array.isArray(deviceIds) || deviceIds.length === 0 || deviceIds.length > 500) {
    return res.json(fail(2001, 'device_ids must be an array with 1-500 items'))
  }
  const { created, failed } = await deviceDao.createBatch(deviceIds)
  await logDao.write({ admin_id: req.admin.admin_id, action: 'admin_device_batch_create', detail: '批量预生成产品码: ' + created + '/' + deviceIds.length, ip: req.ip })
  res.json(ok({ created, failed }))
}))

router.get('/devices/:device_id', requireAdmin, wrap(async (req, res) => {
  const result = await deviceDao.findByIdWithHistory(req.params.device_id)
  if (!result || !result.device) return res.json(fail(1005, 'DEVICE_NOT_FOUND'))
  res.json(ok(Object.assign({}, result.device, { binding_history: result.binding_history, recent_treatments: result.recent_treatments })))
}))

router.post('/devices/:device_id/unbind', requireAdmin, wrap(async (req, res) => {
  await deviceDao.unbind(req.params.device_id)
  await logDao.write({ admin_id: req.admin.admin_id, action: 'admin_device_unbind', detail: '后台解绑设备: ' + req.params.device_id, ip: req.ip })
  res.json(ok({ message: 'success' }))
}))

router.post('/devices/:device_id/command', requireAdmin, wrap(async (req, res) => {
  const opcode = parseInt(req.body.opcode, 10)
  if (!opcode) return res.json(fail(2001, 'opcode required'))
  await commandDao.create(req.params.device_id, req.admin.admin_id, opcode, req.body)
  await logDao.write({ admin_id: req.admin.admin_id, action: 'admin_device_command', detail: '记录远程指令: ' + req.params.device_id, ip: req.ip })
  res.json(ok({ message: 'queued', command: req.body }))
}))

router.get('/devices/:device_id/commands', requireAdmin, wrap(async (req, res) => {
  const { page, pageSize, offset } = pageParams(req.query)
  const { records, total } = await commandDao.listByDevice(req.params.device_id, { pageSize, offset })
  res.json(ok({ records, total }))
}))

// --- Users ---

router.get('/users', requireAdmin, wrap(async (req, res) => {
  const { page, pageSize, offset } = pageParams(req.query)
  const { records, total } = await userDao.listAdmin({
    keyword: req.query.keyword,
    pageSize,
    offset
  })
  res.json(ok({ records, total }))
}))

router.get('/users/:user_id', requireAdmin, wrap(async (req, res) => {
  const result = await userDao.findByIdAdmin(req.params.user_id)
  if (!result) return res.json(fail(1004, 'USER_NOT_FOUND'))
  res.json(ok(result))
}))

router.post('/users/:user_id/unbind', requireAdmin, wrap(async (req, res) => {
  const userId = req.params.user_id
  const targetUser = await userDao.findById(userId)
  if (!targetUser) return res.json(fail(1004, 'USER_NOT_FOUND'))
  const deviceId = req.body.device_id ? String(req.body.device_id).trim() : null
  const result = await bindingDao.unbindByUser(userId, deviceId)
  await logDao.write({
    admin_id: req.admin.admin_id,
    user_id: userId,
    action: 'admin_user_unbind',
    detail: '后台解绑用户设备: user=' + userId + ', device=' + (deviceId || 'all'),
    ip: req.ip
  })
  res.json(ok({ message: 'success', affected_rows: result.affectedRows || 0 }))
}))

router.post('/users/:user_id/deactivate', requireAdmin, wrap(async (req, res) => {
  const userId = req.params.user_id
  const targetUser = await userDao.findById(userId)
  if (!targetUser) return res.json(fail(1004, 'USER_NOT_FOUND'))
  const result = await userDao.deactivate(userId)
  await logDao.write({
    admin_id: req.admin.admin_id,
    user_id: userId,
    action: 'admin_user_deactivate',
    detail: '后台注销用户: user=' + userId + ', unbound=' + result.unboundRows,
    ip: req.ip
  })
  res.json(ok({ message: 'success', unbound_rows: result.unboundRows }))
}))

// --- Subscriptions ---

router.get('/subscriptions', requireAdmin, wrap(async (req, res) => {
  const { page, pageSize, offset } = pageParams(req.query)
  const { records, total } = await subscriptionDao.list({
    tab: req.query.tab,
    pageSize,
    offset
  })
  const stats = await subscriptionDao.getStats()
  res.json(ok({ records, total, stats }))
}))

router.post('/subscriptions', requireAdmin, wrap(async (req, res) => {
  const userId = req.body.user_id
  if (!userId) return res.json(fail(2001, 'user_id required'))
  const targetUser = await userDao.findById(userId)
  if (!targetUser) return res.json(fail(1004, 'user_not_found'))
  await subscriptionDao.adminCreate(
    userId,
    req.body.plan || 'monthly',
    req.body.amount || 0,
    req.body.order_id || 'ADMIN' + Date.now(),
    req.body.days || 30
  )
  res.json(ok({ message: 'success' }))
}))

router.post('/subscriptions/cancel', requireAdmin, wrap(async (req, res) => {
  const subscriptionId = req.body.subscription_id
  if (!subscriptionId) return res.json(fail(2001, 'subscription_id required'))
  const result = await subscriptionDao.cancel(subscriptionId)
  if (result.affectedRows === 0) return res.json(fail(2001, '未找到有效订阅'))
  await logDao.write({ admin_id: req.admin.admin_id, action: 'subscription_cancel', detail: '取消订阅 #' + subscriptionId, ip: req.ip })
  res.json(ok({ message: 'success' }))
}))

// --- Treatment Records ---

router.get('/records', requireAdmin, wrap(async (req, res) => {
  const { page, pageSize, offset } = pageParams(req.query)
  const { records, total } = await treatmentDao.listAdmin({
    keyword: req.query.keyword,
    userId: req.query.user_id,
    dateFrom: req.query.date_from,
    dateTo: req.query.date_to,
    pageSize,
    offset
  })
  res.json(ok({ records, total }))
}))

// --- Logs ---

router.get('/logs', requireAdmin, wrap(async (req, res) => {
  const { page, pageSize, offset } = pageParams(req.query)
  const { records, total } = await logDao.list({
    type: req.query.type,
    deviceId: req.query.device_id,
    pageSize,
    offset
  })
  res.json(ok({ records, total }))
}))

// --- Settings ---

router.get('/settings', requireAdmin, wrap(async (req, res) => {
  const settings = await settingsDao.getAll()
  res.json(ok(settings))
}))

router.post('/settings', requireAdmin, wrap(async (req, res) => {
  const ALLOWED_KEYS = ['system_name', 'admin_email', 'timezone', 'monthly_price', 'yearly_price', 'trial_days', 'enable_register', 'enable_binding', 'enable_free_mode', 'enable_smart_mode', 'maintenance_mode']
  for (const key of Object.keys(req.body || {})) {
    if (!ALLOWED_KEYS.includes(key)) continue
    await settingsDao.update(key, req.body[key])
  }
  invalidateCache()
  res.json(ok({ message: 'success' }))
}))

module.exports = router
