const express = require('express')
const { getSituation } = require('./situationData')
const { getStats } = require('./stats')
const db = require('./db')

const router = express.Router()

/** 由 index.js 注入，确保修订后能触发 WebSocket 广播（不依赖 req.app） */
let _broadcastSituation = null
function setBroadcastSituation(fn) {
  _broadcastSituation = typeof fn === 'function' ? fn : null
}
router.setBroadcastSituation = setBroadcastSituation

// 简单鉴权：通过环境变量配置的 API_ADMIN_KEY 保护敏感接口（不返回真实密钥）
const ADMIN_API_KEY = process.env.API_ADMIN_KEY || ''

function requireAdmin(req, res, next) {
  if (!ADMIN_API_KEY) {
    return res.status(500).json({ error: 'admin key not configured' })
  }
  const token = req.headers['x-api-key']
  if (typeof token !== 'string' || token !== ADMIN_API_KEY) {
    return res.status(401).json({ error: 'unauthorized' })
  }
  return next()
}

// 数据库 Dashboard：返回各表原始数据（需 admin 鉴权）
router.get('/db/dashboard', requireAdmin, (req, res) => {
  try {
    const tables = [
      'feedback',
      'situation',
      'force_summary',
      'power_index',
      'force_asset',
      'key_location',
      'combat_losses',
      'wall_street_trend',
      'retaliation_current',
      'retaliation_history',
      'situation_update',
      'news_content',
      'gdelt_events',
      'conflict_stats',
    ]
    const data = {}
    const timeSort = {
      feedback: 'created_at DESC',
      situation: 'updated_at DESC',
      situation_update: 'timestamp DESC',
      news_content: 'published_at DESC',
      gdelt_events: 'event_time DESC',
      wall_street_trend: 'time DESC',
      retaliation_history: 'time DESC',
      conflict_stats: 'updated_at DESC',
    }
    for (const name of tables) {
      try {
        const order = timeSort[name]
        let rows
        try {
          rows = order
            ? db.prepare(`SELECT * FROM ${name} ORDER BY ${order}`).all()
            : db.prepare(`SELECT * FROM ${name}`).all()
        } catch (qerr) {
          rows = db.prepare(`SELECT * FROM ${name}`).all()
        }
        data[name] = rows
      } catch (e) {
        data[name] = { error: e.message }
      }
    }
    res.json(data)
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

// 资讯内容（独立表，供后续消费，可选 admin key；若配置了 ADMIN_API_KEY 则也要求鉴权）
router.get('/news', (req, res) => {
  if (ADMIN_API_KEY) {
    const token = req.headers['x-api-key']
    if (typeof token !== 'string' || token !== ADMIN_API_KEY) {
      return res.status(401).json({ error: 'unauthorized' })
    }
  }
  try {
    const limit = Math.min(parseInt(req.query.limit, 10) || 50, 200)
    const rows = db.prepare('SELECT id, title, summary, url, source, published_at, category, severity, created_at FROM news_content ORDER BY published_at DESC LIMIT ?').all(limit)
    res.json({ items: rows })
  } catch (err) {
    res.status(500).json({ error: err.message })
  }
})

router.get('/situation', (req, res) => {
  try {
    res.json(getSituation())
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

// 来访统计：记录 IP（或开发环境下每标签 viewer-id），返回在看/看过
function getClientIp(req) {
  const forwarded = req.headers['x-forwarded-for']
  if (forwarded) return forwarded.split(',')[0].trim()
  return req.ip || req.socket?.remoteAddress || 'unknown'
}

// 优先用前端传来的 viewer-id 去重（每设备一个），否则用 IP，这样多设备同 WiFi 也能正确统计「在看」
function getVisitKey(req) {
  const vid = req.headers['x-viewer-id']
  const ip = getClientIp(req)
  if (typeof vid === 'string' && vid.trim().length > 0) {
    return 'vid:' + vid.trim().slice(0, 64)
  }
  return ip
}

router.post('/visit', (req, res) => {
  try {
    const visitKey = getVisitKey(req)
    db.prepare(
      "INSERT OR REPLACE INTO visits (ip, last_seen) VALUES (?, datetime('now'))"
    ).run(visitKey)
    db.prepare(
      'INSERT INTO visitor_count (id, total) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET total = total + 1'
    ).run()
    const broadcast = req.app?.get?.('broadcastSituation')
    if (typeof broadcast === 'function') broadcast()
    res.json(getStats())
  } catch (err) {
    console.error(err)
    res.status(500).json({ viewers: 0, cumulative: 0, feedbackCount: 0, shareCount: 0, likeCount: 0 })
  }
})

router.post('/feedback', (req, res) => {
  try {
    const content = (req.body?.content ?? '').toString().trim()
    if (!content || content.length > 2000) {
      return res.status(400).json({ ok: false, error: '留言内容 1–2000 字' })
    }
    const ip = getClientIp(req)
    db.prepare(
      'INSERT INTO feedback (content, ip) VALUES (?, ?)'
    ).run(content.slice(0, 2000), ip)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(500).json({ ok: false, error: err.message })
  }
})

router.post('/share', (req, res) => {
  try {
    db.prepare(
      'INSERT INTO share_count (id, total) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET total = total + 1'
    ).run()
    const shareCount = db.prepare('SELECT total FROM share_count WHERE id = 1').get()?.total ?? 0
    res.json({ ok: true, shareCount })
  } catch (err) {
    console.error(err)
    res.status(500).json({ ok: false, shareCount: 0 })
  }
})

router.post('/like', (req, res) => {
  try {
    db.prepare(
      'INSERT INTO like_count (id, total) VALUES (1, 1) ON CONFLICT(id) DO UPDATE SET total = total + 1'
    ).run()
    res.json(getStats())
  } catch (err) {
    console.error(err)
    res.status(500).json({ viewers: 0, cumulative: 0, feedbackCount: 0, shareCount: 0, likeCount: 0 })
  }
})

router.get('/stats', (req, res) => {
  try {
    res.json(getStats())
  } catch (err) {
    console.error(err)
    res.status(500).json({ viewers: 0, cumulative: 0, feedbackCount: 0, shareCount: 0, likeCount: 0 })
  }
})

// 战区地图配置：钳形轴线、以黎轴线、防御线路径，供前端 useWarMapData 拉取；新增/修改数据落库
router.get('/war-map-config', (req, res) => {
  try {
    const row = db.prepare('SELECT config FROM war_map_config WHERE id = 1').get()
    if (!row || !row.config) {
      return res.json({})
    }
    const data = JSON.parse(row.config)
    res.json(data)
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

router.put('/war-map-config', requireAdmin, (req, res) => {
  try {
    const body = req.body || {}
    const pincerAxes = Array.isArray(body.pincerAxes) ? body.pincerAxes : null
    const israelLebanonAxis = body.israelLebanonAxis && typeof body.israelLebanonAxis === 'object' ? body.israelLebanonAxis : null
    const defenseLinePath = Array.isArray(body.defenseLinePath) ? body.defenseLinePath : null
    if (!pincerAxes?.length || !israelLebanonAxis || !defenseLinePath?.length) {
      return res.status(400).json({ error: 'pincerAxes (array), israelLebanonAxis (object), defenseLinePath (array) required' })
    }
    const config = JSON.stringify({ pincerAxes, israelLebanonAxis, defenseLinePath })
    db.prepare(
      'INSERT INTO war_map_config (id, config, updated_at) VALUES (1, ?, datetime(\'now\')) ON CONFLICT(id) DO UPDATE SET config = excluded.config, updated_at = datetime(\'now\')'
    ).run(config)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

router.get('/events', (req, res) => {
  try {
    const s = getSituation()
    res.json({
      updated_at: s.lastUpdated,
      count: (s.conflictEvents || []).length,
      events: s.conflictEvents || [],
      conflict_stats: s.conflictStats || {},
    })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

// ---------- 手动修正看板数据（编辑页用） ----------
function broadcastAfterEdit(req) {
  try {
    const broadcast = _broadcastSituation || req.app?.get?.('broadcastSituation')
    if (typeof broadcast === 'function') broadcast()
  } catch (_) {}
}

/** GET 原始可编辑数据：战损、据点、事件脉络、军力概要 */
router.get('/edit/raw', (req, res) => {
  try {
    const lossesUs = db.prepare('SELECT * FROM combat_losses WHERE side = ?').get('us')
    const lossesIr = db.prepare('SELECT * FROM combat_losses WHERE side = ?').get('iran')
    const locUs = db.prepare('SELECT id, side, name, lat, lng, type, region, status, damage_level, attacked_at FROM key_location WHERE side = ?').all('us')
    const locIr = db.prepare('SELECT id, side, name, lat, lng, type, region, status, damage_level, attacked_at FROM key_location WHERE side = ?').all('iran')
    const updates = db.prepare('SELECT id, timestamp, category, summary, severity FROM situation_update ORDER BY timestamp DESC LIMIT 80').all()
    const summaryUs = db.prepare('SELECT * FROM force_summary WHERE side = ?').get('us')
    const summaryIr = db.prepare('SELECT * FROM force_summary WHERE side = ?').get('iran')
    let displayStats = null
    let animationConfig = null
    try {
      displayStats = db.prepare('SELECT override_enabled, viewers, cumulative, share_count, like_count, feedback_count FROM display_stats WHERE id = 1').get()
    } catch (_) {}
    try {
      animationConfig = db.prepare('SELECT strike_cutoff_days FROM animation_config WHERE id = 1').get()
    } catch (_) {}
    let crawlerConfig = null
    try {
      crawlerConfig = db.prepare('SELECT rss_interval_sec FROM crawler_config WHERE id = 1').get()
    } catch (_) {}
    const realCumulative = db.prepare('SELECT total FROM visitor_count WHERE id = 1').get()?.total ?? 0
    const realShare = db.prepare('SELECT total FROM share_count WHERE id = 1').get()?.total ?? 0
    const liveViewers = db.prepare(
      "SELECT COUNT(*) as n FROM visits WHERE last_seen > datetime('now', '-2 minutes')"
    ).get()?.n ?? 0
    const realFeedback = db.prepare('SELECT COUNT(*) as n FROM feedback').get()?.n ?? 0
    let realLikeCount = 0
    try {
      realLikeCount = db.prepare('SELECT total FROM like_count WHERE id = 1').get()?.total ?? 0
    } catch (_) {}
    res.json({
      combatLosses: { us: lossesUs || null, iran: lossesIr || null },
      keyLocations: { us: locUs || [], iran: locIr || [] },
      situationUpdates: updates || [],
      forceSummary: { us: summaryUs || null, iran: summaryIr || null },
      displayStats: {
        overrideEnabled: displayStats?.override_enabled === 1,
        viewers: displayStats?.viewers ?? liveViewers,
        cumulative: displayStats?.cumulative ?? realCumulative,
        shareCount: displayStats?.share_count ?? realShare,
        likeCount: displayStats?.like_count ?? realLikeCount,
        feedbackCount: displayStats?.feedback_count ?? realFeedback,
      },
      animationConfig: {
        strikeCutoffDays: animationConfig?.strike_cutoff_days ?? 5,
      },
      crawlerConfig: {
        rssIntervalSec: crawlerConfig?.rss_interval_sec ?? 60,
      },
    })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** GET 留言列表（修订页查看） */
router.get('/edit/feedback', (req, res) => {
  try {
    const list = db.prepare('SELECT id, content, ip, created_at FROM feedback ORDER BY id DESC LIMIT 500').all()
    res.json({ list })
  } catch (err) {
    console.error('[edit/feedback]', err?.message || err)
    // 表不存在或列缺失时返回空列表，避免修订页报错
    res.json({ list: [] })
  }
})

/** PUT 爬虫配置（RSS 抓取间隔等，爬虫从同一 DB 读取） */
router.put('/edit/crawler-config', (req, res) => {
  try {
    const n = req.body?.rssIntervalSec
    if (n === undefined) return res.status(400).json({ error: 'rssIntervalSec required' })
    const val = parseInt(String(n), 10)
    if (!Number.isFinite(val) || val < 30 || val > 86400) return res.status(400).json({ error: 'rssIntervalSec must be 30–86400' })
    db.prepare('INSERT OR REPLACE INTO crawler_config (id, rss_interval_sec) VALUES (1, ?)').run(val)
    res.json({ ok: true, rssIntervalSec: val })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** PUT 更新战损（美/伊） */
router.put('/edit/combat-losses', (req, res) => {
  try {
    const side = req.body?.side
    if (side !== 'us' && side !== 'iran') {
      return res.status(400).json({ error: 'side must be us or iran' })
    }
    const row = db.prepare('SELECT * FROM combat_losses WHERE side = ?').get(side)
    if (!row) return res.status(404).json({ error: 'combat_losses row not found' })
    const cols = ['bases_destroyed', 'bases_damaged', 'personnel_killed', 'personnel_wounded',
      'civilian_killed', 'civilian_wounded', 'aircraft', 'warships', 'armor', 'vehicles',
      'drones', 'missiles', 'helicopters', 'submarines', 'tanks', 'carriers', 'civilian_ships', 'airport_port']
    const updates = []
    const values = []
    for (const c of cols) {
      if (req.body[c] !== undefined) {
        updates.push(`${c} = ?`)
        values.push(Number(req.body[c]) || 0)
      }
    }
    if (updates.length === 0) return res.status(400).json({ error: 'no fields to update' })
    values.push(side)
    db.prepare(`UPDATE combat_losses SET ${updates.join(', ')} WHERE side = ?`).run(...values)
    db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run(new Date().toISOString())
    broadcastAfterEdit(req)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** PATCH 更新单个据点 */
router.patch('/edit/key-location/:id', (req, res) => {
  try {
    const id = parseInt(req.params.id, 10)
    if (!Number.isFinite(id)) return res.status(400).json({ error: 'invalid id' })
    const row = db.prepare('SELECT id FROM key_location WHERE id = ?').get(id)
    if (!row) return res.status(404).json({ error: 'key_location not found' })
    const allowed = ['name', 'lat', 'lng', 'type', 'region', 'status', 'damage_level', 'attacked_at']
    const updates = []
    const values = []
    for (const k of allowed) {
      if (req.body[k] !== undefined) {
        if (k === 'status' && !['operational', 'damaged', 'attacked'].includes(req.body[k])) continue
        updates.push(`${k} = ?`)
        values.push(k === 'lat' || k === 'lng' ? Number(req.body[k]) : req.body[k])
      }
    }
    if (updates.length === 0) return res.status(400).json({ error: 'no fields to update' })
    values.push(id)
    db.prepare(`UPDATE key_location SET ${updates.join(', ')} WHERE id = ?`).run(...values)
    db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run(new Date().toISOString())
    broadcastAfterEdit(req)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** POST 新增事件脉络 */
router.post('/edit/situation-update', (req, res) => {
  try {
    const id = (req.body?.id || '').toString().trim() || `man_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`
    const timestamp = (req.body?.timestamp || new Date().toISOString()).toString().trim()
    const category = (req.body?.category || 'other').toString().toLowerCase()
    const summary = (req.body?.summary || '').toString().trim().slice(0, 500)
    const severity = (req.body?.severity || 'medium').toString().toLowerCase()
    if (!summary) return res.status(400).json({ error: 'summary required' })
    const validCat = ['deployment', 'alert', 'intel', 'diplomatic', 'other'].includes(category) ? category : 'other'
    const validSev = ['low', 'medium', 'high', 'critical'].includes(severity) ? severity : 'medium'
    db.prepare('INSERT OR REPLACE INTO situation_update (id, timestamp, category, summary, severity) VALUES (?, ?, ?, ?, ?)').run(id, timestamp, validCat, summary, validSev)
    db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run(new Date().toISOString())
    broadcastAfterEdit(req)
    res.json({ ok: true, id })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** DELETE 删除一条事件脉络 */
router.delete('/edit/situation-update/:id', (req, res) => {
  try {
    const id = (req.params.id || '').toString().trim()
    if (!id) return res.status(400).json({ error: 'id required' })
    const r = db.prepare('DELETE FROM situation_update WHERE id = ?').run(id)
    if (r.changes === 0) return res.status(404).json({ error: 'not found' })
    db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run(new Date().toISOString())
    broadcastAfterEdit(req)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** PUT 更新军力概要（美/伊） */
router.put('/edit/force-summary', (req, res) => {
  try {
    const side = req.body?.side
    if (side !== 'us' && side !== 'iran') {
      return res.status(400).json({ error: 'side must be us or iran' })
    }
    const cols = ['total_assets', 'personnel', 'naval_ships', 'aircraft', 'ground_units', 'uav', 'missile_consumed', 'missile_stock']
    const updates = []
    const values = []
    for (const c of cols) {
      if (req.body[c] !== undefined) {
        updates.push(`${c} = ?`)
        values.push(Number(req.body[c]) || 0)
      }
    }
    if (updates.length === 0) return res.status(400).json({ error: 'no fields to update' })
    values.push(side)
    db.prepare(`UPDATE force_summary SET ${updates.join(', ')} WHERE side = ?`).run(...values)
    db.prepare("INSERT OR REPLACE INTO situation (id, data, updated_at) VALUES (1, '{}', ?)").run(new Date().toISOString())
    broadcastAfterEdit(req)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(500).json({ error: err.message })
  }
})

/** PUT 更新展示统计（看过、在看、分享、点赞、留言）。传 null 表示清除该字段；clearOverride=true 或全部为 null 时关闭覆盖、恢复实时统计 */
router.put('/edit/display-stats', (req, res) => {
  try {
    db.prepare('INSERT OR IGNORE INTO display_stats (id) VALUES (1)').run()
    const body = req.body || {}
    const clearOverride = body.clearOverride === true || body.clearOverride === 'true'
    const viewers = body.viewers
    const cumulative = body.cumulative
    const shareCount = body.shareCount
    const likeCount = body.likeCount
    const feedbackCount = body.feedbackCount
    const allNull = viewers === null && cumulative === null && shareCount === null && likeCount === null && feedbackCount === null

    if (clearOverride || allNull) {
      db.prepare(
        'UPDATE display_stats SET override_enabled = 0, viewers = NULL, cumulative = NULL, share_count = NULL, like_count = NULL, feedback_count = NULL WHERE id = 1'
      ).run()
      broadcastAfterEdit(req)
      return res.json({ ok: true })
    }

    const updates = []
    const values = []
    const setField = (key, bodyKey) => {
      const v = body[bodyKey ?? key]
      if (v === undefined) return
      if (v === null) {
        updates.push(`${key} = ?`)
        values.push(null)
        return
      }
      const n = Math.max(0, parseInt(v, 10))
      if (!Number.isFinite(n)) throw new Error(`${bodyKey ?? key} must be number`)
      updates.push(`${key} = ?`)
      values.push(n)
    }
    setField('viewers')
    setField('cumulative')
    setField('share_count', 'shareCount')
    setField('like_count', 'likeCount')
    setField('feedback_count', 'feedbackCount')
    if (updates.length === 0) return res.status(400).json({ error: 'no fields to update' })
    updates.push('override_enabled = ?')
    values.push(1)
    values.push(1)
    db.prepare(`UPDATE display_stats SET ${updates.join(', ')} WHERE id = ?`).run(...values)
    broadcastAfterEdit(req)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(400).json({ error: err.message })
  }
})

router.put('/edit/animation-config', (req, res) => {
  try {
    const body = req.body || {}
    const v = body.strikeCutoffDays
    const n = Math.max(1, parseInt(v, 10) || 0)
    if (!Number.isFinite(n)) return res.status(400).json({ error: 'strikeCutoffDays must be number' })
    db.prepare('INSERT OR IGNORE INTO animation_config (id, strike_cutoff_days) VALUES (1, 5)').run()
    db.prepare('UPDATE animation_config SET strike_cutoff_days = ?, updated_at = datetime(\'now\') WHERE id = 1').run(n)
    broadcastAfterEdit(req)
    res.json({ ok: true })
  } catch (err) {
    console.error(err)
    res.status(400).json({ error: err.message })
  }
})

module.exports = router
