const db = require('../db/db');
const { AVATAR_FRAMES } = require('./gamification/_shared');

/* Resolve a frame slug to { id, css }. Slug can be either a gamification
   frame id (e.g. 'fire', 'crown') or a shop-purchased frame stored as
   'shop_<itemId>'. Returns null for 'default' / unknown. */
function resolveFrame(slug) {
  if (!slug || slug === 'default') return null;
  if (slug.startsWith('shop_')) {
    const itemId = Number(slug.slice(5));
    if (!Number.isFinite(itemId)) return null;
    const item = db.prepare('SELECT data FROM shop_items WHERE id = ? AND type = ?').get(itemId, 'frame');
    if (!item) return null;
    try {
      const data = JSON.parse(item.data || '{}');
      return { id: slug, css: data.css || '' };
    } catch { return { id: slug, css: '' }; }
  }
  const f = AVATAR_FRAMES.find(fr => fr.id === slug);
  return f ? { id: f.id, css: f.css || '' } : null;
}

/* ═══════════════════════════════════════════════════════════════════════
   Shop — Items, Purchases, Coins
   ═══════════════════════════════════════════════════════════════════════ */

/* GET /api/shop/items — list all active shop items + owned status */
function getItems(req, res) {
  const userId = req.user.id;
  const items = db.prepare(`
    SELECT si.*,
           (SELECT 1 FROM user_purchases up WHERE up.item_id = si.id AND up.user_id = ?) AS owned
    FROM shop_items si
    WHERE si.is_active = 1
    ORDER BY si.price
  `).all(userId);

  const user = db.prepare('SELECT coins FROM users WHERE id = ?').get(userId);
  res.json({ items, coins: (user && user.coins) || 0 });
}

/* POST /api/shop/items/:id/purchase — buy an item (atomic transaction) */
function purchaseItem(req, res) {
  const userId = req.user.id;
  const itemId = Number(req.params.id);

  const item = db.prepare('SELECT * FROM shop_items WHERE id = ? AND is_active = 1').get(itemId);
  if (!item) return res.status(404).json({ error: 'Предмет не найден' });

  const alreadyOwned = db.prepare('SELECT 1 FROM user_purchases WHERE user_id = ? AND item_id = ?').get(userId, itemId);
  if (alreadyOwned) return res.status(400).json({ error: 'Вы уже купили этот предмет' });

  // Atomic: conditional UPDATE (race-safe even under concurrent purchases)
  const doPurchase = db.transaction(() => {
    const upd = db.prepare(
      'UPDATE users SET coins = coins - ? WHERE id = ? AND coins >= ?'
    ).run(item.price, userId, item.price);
    if (upd.changes === 0) return { err: 'Недостаточно монет' };
    db.prepare('INSERT INTO user_purchases (user_id, item_id) VALUES (?, ?)').run(userId, itemId);
    const updated = db.prepare('SELECT coins FROM users WHERE id = ?').get(userId);
    return { coins: (updated && updated.coins) || 0 };
  });

  const result = doPurchase();
  if (result.err) return res.status(400).json({ error: result.err });
  res.json({ ok: true, coins: result.coins, item });
}

/* GET /api/shop/purchases — list user's purchases with item details */
function getPurchases(req, res) {
  const rows = db.prepare(`
    SELECT up.id AS purchase_id, up.purchased_at, si.*
    FROM user_purchases up
    JOIN shop_items si ON si.id = up.item_id
    WHERE up.user_id = ?
    ORDER BY up.purchased_at DESC
  `).all(req.user.id);
  res.json(rows);
}

/* GET /api/shop/coins — return user's coin balance */
function getCoins(req, res) {
  const user = db.prepare('SELECT coins FROM users WHERE id = ?').get(req.user.id);
  res.json({ coins: (user && user.coins) || 0 });
}

/* GET /api/shop/my-active — return user's active cosmetics */
function getMyActive(req, res) {
  const u = db.prepare('SELECT avatar_frame, active_title, active_effect, active_background FROM users WHERE id = ?').get(req.user.id);
  if (!u) return res.json({});
  // Resolve full data for each active item
  const result = { frame: null, title: null, effect: null, background: null };

  // Frame: resolve either a gamification frame ('fire', 'crown', ...) or
  // a shop-purchased one ('shop_<id>') to { id, css } so applyCosmetics
  // on the client can render it without an extra round-trip.
  result.frame = resolveFrame(u.avatar_frame);

  if (u.active_title) {
    const item = db.prepare('SELECT data FROM shop_items WHERE id = ?').get(u.active_title);
    if (item) try { result.title = JSON.parse(item.data); } catch {}
  }
  if (u.active_effect) {
    const item = db.prepare('SELECT data FROM shop_items WHERE id = ?').get(u.active_effect);
    if (item) try { result.effect = JSON.parse(item.data); } catch {}
  }
  // Background: stored as the bare slug (e.g. 'aurora') in users.active_background.
  // 'none' / null → no extra rendering on the client.
  if (u.active_background && u.active_background !== 'none') {
    result.background = { slug: u.active_background };
  }
  res.json(result);
}

/* POST /api/shop/activate — activate a purchased item (or deactivate with itemId=null) */
function activateItem(req, res) {
  const userId = req.user.id;
  const { itemId } = req.body;

  // Deactivate: pass itemId = null and type
  if (!itemId) {
    const { type } = req.body;
    if (type === 'title')      db.prepare('UPDATE users SET active_title = NULL WHERE id = ?').run(userId);
    if (type === 'effect')     db.prepare('UPDATE users SET active_effect = NULL WHERE id = ?').run(userId);
    if (type === 'frame')      db.prepare("UPDATE users SET avatar_frame = 'default' WHERE id = ?").run(userId);
    if (type === 'background') db.prepare('UPDATE users SET active_background = NULL WHERE id = ?').run(userId);
    return res.json({ ok: true });
  }

  const item = db.prepare('SELECT * FROM shop_items WHERE id = ?').get(itemId);
  if (!item) return res.status(404).json({ error: 'Предмет не найден' });

  // Free items (price=0) skip the ownership check — backgrounds &
  // future freebies are available to everyone without a purchase row.
  if (item.price > 0) {
    const owned = db.prepare('SELECT 1 FROM user_purchases WHERE user_id = ? AND item_id = ?').get(userId, itemId);
    if (!owned) return res.status(403).json({ error: 'Предмет не куплен' });
  }

  let data;
  try { data = JSON.parse(item.data); } catch { data = {}; }

  if (item.type === 'frame')      db.prepare('UPDATE users SET avatar_frame = ? WHERE id = ?').run('shop_' + itemId, userId);
  if (item.type === 'title')      db.prepare('UPDATE users SET active_title = ? WHERE id = ?').run(itemId, userId);
  if (item.type === 'effect')     db.prepare('UPDATE users SET active_effect = ? WHERE id = ?').run(itemId, userId);
  if (item.type === 'background') {
    const slug = (data && data.slug) || 'none';
    db.prepare('UPDATE users SET active_background = ? WHERE id = ?').run(slug, userId);
  }

  res.json({ ok: true, type: item.type, data });
}

/* ═══════════════════════════════════════════════════════════════════════
   Admin — CRUD shop items, award coins, stats
   ═══════════════════════════════════════════════════════════════════════ */

/* GET /api/shop/admin/items — all items (including inactive) */
function adminGetItems(_req, res) {
  const items = db.prepare(`
    SELECT si.*,
           (SELECT COUNT(*) FROM user_purchases up WHERE up.item_id = si.id) AS sold_count
    FROM shop_items si ORDER BY si.id
  `).all();
  res.json(items);
}

/* POST /api/shop/admin/items — create item */
function adminCreateItem(req, res) {
  const { name, description, type, category, price, data, icon, is_active } = req.body;
  if (!name || !type || price == null) return res.status(400).json({ error: 'name, type, price required' });
  const r = db.prepare(
    'INSERT INTO shop_items (name, description, type, category, price, data, icon, is_active) VALUES (?,?,?,?,?,?,?,?)'
  ).run(name, description || '', type, category || 'cosmetic', price, data || '{}', icon || 'star', is_active ?? 1);
  res.json({ ok: true, id: r.lastInsertRowid });
}

/* PUT /api/shop/admin/items/:id — update item */
function adminUpdateItem(req, res) {
  const id = Number(req.params.id);
  const item = db.prepare('SELECT * FROM shop_items WHERE id = ?').get(id);
  if (!item) return res.status(404).json({ error: 'Item not found' });
  const { name, description, type, category, price, data, icon, is_active } = req.body;
  db.prepare(`UPDATE shop_items SET
    name=COALESCE(?,name), description=COALESCE(?,description), type=COALESCE(?,type),
    category=COALESCE(?,category), price=COALESCE(?,price), data=COALESCE(?,data),
    icon=COALESCE(?,icon), is_active=COALESCE(?,is_active) WHERE id=?`
  ).run(name, description, type, category, price, data, icon, is_active, id);
  res.json({ ok: true });
}

/* DELETE /api/shop/admin/items/:id — delete item */
function adminDeleteItem(req, res) {
  const id = Number(req.params.id);
  db.prepare('DELETE FROM user_purchases WHERE item_id = ?').run(id);
  db.prepare('DELETE FROM shop_items WHERE id = ?').run(id);
  res.json({ ok: true });
}

/* POST /api/shop/admin/award-coins — award coins to user */
const SHOP_AWARD_MAX = 1_000_000;
function adminAwardCoins(req, res) {
  const { userId, amount, reason } = req.body;
  const amt = Number(amount);
  if (!userId || !Number.isFinite(amt) || amt <= 0 || amt > SHOP_AWARD_MAX)
    return res.status(400).json({ error: `userId and amount (1..${SHOP_AWARD_MAX}) required` });
  const result = db.prepare('UPDATE users SET coins = coins + ? WHERE id = ?').run(amt, userId);
  if (result.changes === 0) return res.status(404).json({ error: 'User not found' });
  const user = db.prepare('SELECT coins FROM users WHERE id = ?').get(userId);
  res.json({ ok: true, coins: user?.coins || 0 });
}

/* GET /api/shop/admin/stats — shop stats */
function adminShopStats(_req, res) {
  const totalItems = db.prepare('SELECT COUNT(*) as c FROM shop_items').get().c;
  const activeItems = db.prepare('SELECT COUNT(*) as c FROM shop_items WHERE is_active=1').get().c;
  const totalPurchases = db.prepare('SELECT COUNT(*) as c FROM user_purchases').get().c;
  const totalCoinsInCirculation = db.prepare('SELECT COALESCE(SUM(coins),0) as c FROM users').get().c;
  const topItems = db.prepare(`
    SELECT si.name, si.price, COUNT(up.id) as sold
    FROM shop_items si LEFT JOIN user_purchases up ON up.item_id = si.id
    GROUP BY si.id ORDER BY sold DESC LIMIT 5
  `).all();
  res.json({ totalItems, activeItems, totalPurchases, totalCoinsInCirculation, topItems });
}

module.exports = {
  getItems, purchaseItem, getPurchases, getCoins, getMyActive, activateItem,
  adminGetItems, adminCreateItem, adminUpdateItem, adminDeleteItem, adminAwardCoins, adminShopStats
};
