'use strict';

// ── WALLETS ROUTER ────────────────────────────────────────────────
const walletRouter = require('express').Router();
const { body, validationResult } = require('express-validator');
const { query, queryOne } = require('../config/db');
const { requireAuth } = require('../middleware/auth');
const { deriveAddress, testDerivation } = require('../services/wallet');
const COINS = require('../config/coins');

walletRouter.get('/', requireAuth, async (req, res) => {
  const rows = await query('SELECT coin, derivation, gap_limit, current_index, updated_at FROM xpub_keys WHERE user_id = ?', [req.user.id]);
  return res.json({ wallets: rows });
});

walletRouter.put('/:coin', requireAuth,
  [body('xpub').notEmpty(), body('derivation').optional().isString(), body('gap_limit').optional().isInt({ min: 1, max: 100 })],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });

    const { coin } = req.params;
    if (!COINS[coin]) return res.status(400).json({ error: 'Invalid coin.' });

    const { xpub, derivation, gap_limit = 20 } = req.body;

    await query(
      `INSERT INTO xpub_keys (user_id, coin, xpub, derivation, gap_limit)
       VALUES (?, ?, ?, ?, ?)
       ON DUPLICATE KEY UPDATE xpub = VALUES(xpub), derivation = VALUES(derivation), gap_limit = VALUES(gap_limit), current_index = 0, updated_at = NOW()`,
      [req.user.id, coin, xpub, derivation || COINS[coin].derivation, gap_limit]
    );
    return res.json({ ok: true, message: `xPub saved for ${coin}. Index reset to 0.` });
  }
);

walletRouter.post('/:coin/test', requireAuth, async (req, res) => {
  const { coin } = req.params;
  const { xpub } = req.body;
  if (!xpub || !COINS[coin]) return res.status(400).json({ error: 'xpub and valid coin required.' });

  const result = await testDerivation(xpub, coin, 5);
  return res.json(result);
});

walletRouter.post('/:coin/derive', requireAuth, async (req, res) => {
  const { coin } = req.params;
  try {
    const address = await deriveAddress(req.user.id, coin, req.body.store_id || null);
    if (!address) return res.status(400).json({ error: `No xPub configured for ${coin}.` });
    return res.json({ address, coin });
  } catch (err) {
    return res.status(500).json({ error: 'Derivation failed.' });
  }
});

// ── WEBHOOKS ROUTER ───────────────────────────────────────────────
const webhookRouter = require('express').Router();
const { v4: uuidv4 } = require('uuid');
const crypto = require('crypto');
const { testWebhook } = require('../services/webhook');

webhookRouter.get('/', requireAuth, async (req, res) => {
  const rows = await query('SELECT * FROM webhooks WHERE user_id = ?', [req.user.id]);
  return res.json({ webhooks: rows });
});

webhookRouter.post('/', requireAuth,
  [body('url').isURL(), body('events').optional().isArray()],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });

    const { url, events = ['payment.confirmed','payment.detected','payment.underpaid','invoice.expired'] } = req.body;
    const uuid   = uuidv4();
    const secret = 'wsk_' + crypto.randomBytes(20).toString('hex');

    await query(
      'INSERT INTO webhooks (uuid, user_id, url, secret, events) VALUES (?, ?, ?, ?, ?)',
      [uuid, req.user.id, url, secret, JSON.stringify(events)]
    );

    const hook = await queryOne('SELECT * FROM webhooks WHERE uuid = ?', [uuid]);
    return res.status(201).json({ webhook: hook });
  }
);

webhookRouter.put('/:uuid', requireAuth, async (req, res) => {
  const { url, events, status } = req.body;
  const updates = [];
  const params  = [];
  if (url)    { updates.push('url = ?');    params.push(url); }
  if (events) { updates.push('events = ?'); params.push(JSON.stringify(events)); }
  if (status) { updates.push('status = ?'); params.push(status); }
  if (!updates.length) return res.status(400).json({ error: 'Nothing to update.' });
  params.push(req.params.uuid, req.user.id);
  await query(`UPDATE webhooks SET ${updates.join(', ')} WHERE uuid = ? AND user_id = ?`, params);
  return res.json({ ok: true });
});

webhookRouter.delete('/:uuid', requireAuth, async (req, res) => {
  await query('DELETE FROM webhooks WHERE uuid = ? AND user_id = ?', [req.params.uuid, req.user.id]);
  return res.json({ ok: true });
});

webhookRouter.post('/:uuid/test', requireAuth, async (req, res) => {
  const hook = await queryOne('SELECT * FROM webhooks WHERE uuid = ? AND user_id = ?', [req.params.uuid, req.user.id]);
  if (!hook) return res.status(404).json({ error: 'Webhook not found.' });
  const result = await testWebhook(hook.id);
  return res.json(result);
});

webhookRouter.get('/:uuid/logs', requireAuth, async (req, res) => {
  const hook = await queryOne('SELECT id FROM webhooks WHERE uuid = ? AND user_id = ?', [req.params.uuid, req.user.id]);
  if (!hook) return res.status(404).json({ error: 'Webhook not found.' });
  const logs = await query('SELECT * FROM webhook_logs WHERE webhook_id = ? ORDER BY created_at DESC LIMIT 50', [hook.id]);
  return res.json({ logs });
});

// ── SETTINGS ROUTER ───────────────────────────────────────────────
const settingsRouter = require('express').Router();

settingsRouter.get('/', requireAuth, async (req, res) => {
  const s = await queryOne('SELECT * FROM user_settings WHERE user_id = ?', [req.user.id]);
  return res.json({ settings: s });
});

settingsRouter.put('/', requireAuth, async (req, res) => {
  const allowed = [
    'invoice_timeout','underpay_pct','confirmed_status','expired_status','pending_status',
    'smart_routing','eth_fee_threshold','show_qr','show_timer','show_rate','show_fee',
    'notify_confirmed','notify_detected','notify_underpaid','notify_expired','enabled_coins',
  ];
  const updates = [];
  const params  = [];

  for (const key of allowed) {
    if (req.body[key] !== undefined) {
      updates.push(`${key} = ?`);
      const val = key === 'enabled_coins' ? JSON.stringify(req.body[key]) : req.body[key];
      params.push(val);
    }
  }

  if (!updates.length) return res.status(400).json({ error: 'No valid fields.' });

  params.push(req.user.id);
  await query(
    `INSERT INTO user_settings (user_id, ${updates.map(u=>u.split(' = ')[0]).join(',')}) VALUES (?${',?'.repeat(updates.length)})
     ON DUPLICATE KEY UPDATE ${updates.join(', ')}`,
    [req.user.id, ...params.slice(0, -1)]
  ).catch(async () => {
    // Fallback plain UPDATE
    await query(`UPDATE user_settings SET ${updates.join(', ')} WHERE user_id = ?`, params);
  });

  return res.json({ ok: true, message: 'Settings saved.' });
});

// Profile update
settingsRouter.put('/profile', requireAuth,
  [body('name').optional().isLength({ min: 2, max: 120 })],
  async (req, res) => {
    const { name, company, phone } = req.body;
    const updates = [];
    const params  = [];
    if (name)    { updates.push('name = ?');   params.push(name); }
    if (!updates.length) return res.status(400).json({ error: 'Nothing to update.' });
    params.push(req.user.id);
    await query(`UPDATE users SET ${updates.join(', ')} WHERE id = ?`, params);
    return res.json({ ok: true });
  }
);

// ── PRICES ROUTER ─────────────────────────────────────────────────
const pricesRouter = require('express').Router();
const { getAllRates, getRate, getEthGasUsd } = require('../services/prices');

pricesRouter.get('/', async (req, res) => {
  const { currency = 'USD' } = req.query;
  const prices = await getAllRates(currency);
  return res.json({ prices, currency, updated_at: new Date().toISOString() });
});

pricesRouter.get('/:coin', async (req, res) => {
  const { currency = 'USD' } = req.query;
  const rate = await getRate(req.params.coin, currency);
  if (!rate) return res.status(404).json({ error: 'Rate not available.' });
  return res.json({ coin: req.params.coin, currency, rate, updated_at: new Date().toISOString() });
});

pricesRouter.get('/gas/eth', async (req, res) => {
  const usd = await getEthGasUsd();
  return res.json({ gas_usd: usd });
});

// ── API KEYS ROUTER ───────────────────────────────────────────────
const apiKeyRouter = require('express').Router();
const { generateApiKey: genKey } = require('../middleware/auth');

apiKeyRouter.get('/', requireAuth, async (req, res) => {
  const keys = await query(
    'SELECT uuid, name, key_preview, scope, environment, last_used_at, created_at, status, requests_count FROM api_keys WHERE user_id = ?',
    [req.user.id]
  );
  return res.json({ api_keys: keys });
});

apiKeyRouter.post('/', requireAuth,
  [body('name').notEmpty().isLength({ min: 2, max: 120 }), body('scope').optional(), body('environment').optional().isIn(['live','test'])],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });

    const { name, scope = 'full', environment = 'live', store_id } = req.body;
    const { raw, hash, preview, prefix } = genKey(environment);
    const uuid = uuidv4();

    await query(
      'INSERT INTO api_keys (uuid, user_id, store_id, name, key_hash, key_prefix, key_preview, scope, environment) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
      [uuid, req.user.id, store_id || null, name, hash, prefix, preview, scope, environment]
    );

    return res.status(201).json({
      api_key: { uuid, name, key: raw, preview, scope, environment },
      warning: 'Save this key now — it will not be shown again.',
    });
  }
);

apiKeyRouter.delete('/:uuid', requireAuth, async (req, res) => {
  await query('UPDATE api_keys SET status = "revoked" WHERE uuid = ? AND user_id = ?', [req.params.uuid, req.user.id]);
  return res.json({ ok: true, message: 'API key revoked.' });
});

// ── STORES ROUTER ─────────────────────────────────────────────────
const storeRouter = require('express').Router();

storeRouter.get('/', requireAuth, async (req, res) => {
  const stores = await query('SELECT * FROM stores WHERE user_id = ?', [req.user.id]);
  return res.json({ stores });
});

storeRouter.post('/', requireAuth,
  [body('name').notEmpty(), body('url').isURL()],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });

    const { name, url, platform = 'woocommerce' } = req.body;
    const uuid = uuidv4();
    await query(
      'INSERT INTO stores (uuid, user_id, name, url, platform) VALUES (?, ?, ?, ?, ?)',
      [uuid, req.user.id, name, url, platform]
    );
    const store = await queryOne('SELECT * FROM stores WHERE uuid = ?', [uuid]);
    return res.status(201).json({ store });
  }
);

storeRouter.delete('/:uuid', requireAuth, async (req, res) => {
  await query('DELETE FROM stores WHERE uuid = ? AND user_id = ?', [req.params.uuid, req.user.id]);
  return res.json({ ok: true });
});

// Plugin heartbeat — called by WP plugin every hour
storeRouter.post('/:uuid/heartbeat', requireAuth, async (req, res) => {
  const { plugin_version } = req.body;
  await query(
    'UPDATE stores SET last_seen = NOW(), plugin_version = ? WHERE uuid = ? AND user_id = ?',
    [plugin_version || null, req.params.uuid, req.user.id]
  );
  return res.json({ ok: true });
});

module.exports = {
  walletRouter,
  webhookRouter,
  settingsRouter,
  pricesRouter,
  apiKeyRouter,
  storeRouter,
};
