import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import * as cookie from 'cookie';
import { db } from '../core/db.js';
import { processOrderPaid } from '../modules/payment/delivery.js';
import { verifyTripaySignature, verifyMidtransSignature, verifyPakasirCallback } from '../modules/payment/provider.js';
import { loadGuildPaymentConfig, resolveOrderContext } from '../modules/payment/config.js';
import { getUserClient } from '../core/bot-manager.js';
import { apiRouter } from './routes/api.js';
import { authRouter, authMiddleware } from './routes/auth.js';
import { botRouter } from './routes/bot.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

// Minimal cookie parser (pakai package `cookie`, no extra dep)
function cookieParser(req, res, next) {
  req.cookies = req.headers.cookie ? cookie.parse(req.headers.cookie) : {};
  next();
}

export function startWebServer(client) {
  const app = express();
  app.disable('x-powered-by'); // jangan bocorin "Express"
  app.set('discord-client', client);

  // Security headers (manual, tanpa dependency helmet)
  app.use((req, res, next) => {
    res.set('X-Content-Type-Options', 'nosniff');
    res.set('X-Frame-Options', 'DENY');
    res.set('Referrer-Policy', 'strict-origin-when-cross-origin');
    res.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
    next();
  });

  app.use(express.json({ limit: '5mb', verify: (req, res, buf) => { req.rawBody = buf.toString('utf8'); } }));
  app.use(cookieParser);
  app.use(authMiddleware); // attaches req.user when session cookie valid

  // Validate required env vars
  if (!process.env.APP_SECRET || process.env.APP_SECRET.length < 32) {
    console.error('❌ APP_SECRET (min 32 char) wajib di .env untuk enkripsi token & session');
    process.exit(1);
  }
  if (!process.env.DASHBOARD_TOKEN || process.env.DASHBOARD_TOKEN === 'haikz-dash-2026') {
    console.error('❌ DASHBOARD_TOKEN must be set to a strong random value in .env');
    console.error('   Generate one: node -e "console.log(require(\'crypto\').randomBytes(32).toString(\'hex\'))"');
    process.exit(1);
  }
  if (process.env.PAYMENT_PROVIDER === 'tripay') {
    if (!process.env.TRIPAY_API_KEY || !process.env.TRIPAY_PRIVATE_KEY || !process.env.TRIPAY_MERCHANT_CODE) {
      console.error('❌ TRIPAY_API_KEY, TRIPAY_PRIVATE_KEY, TRIPAY_MERCHANT_CODE required when PAYMENT_PROVIDER=tripay');
      process.exit(1);
    }
  }

  // Health
  app.get('/api/health', (_, res) => res.json({ ok: true, name: 'haikz-discord-bot' }));

  // Auth (login/logout/users)
  app.use('/auth', authRouter);

  // Per-user bot management (set token, start/stop, status)
  app.use('/bot', botRouter);

  // Dashboard API
  app.use('/api', apiRouter);

  // Helper: pilih client bot yang benar buat kirim DM (bot owner, fallback bot utama)
  const clientFor = (ownerUserId) => (ownerUserId && getUserClient(ownerUserId)) || client;

  // --- Tripay webhook (multi-tenant, HMAC-SHA256) ---
  app.post('/webhook/tripay', async (req, res) => {
    try {
      const signature = req.headers['x-callback-signature'];
      const merchantRef = req.body?.merchant_ref;
      const status = req.body?.status;
      const amount = req.body?.total_amount ?? req.body?.amount;

      const ctx = resolveOrderContext(merchantRef);
      if (!ctx) return res.status(404).json({ error: 'order not found' });

      // V5: verifikasi pakai private key OWNER guild ini (bukan env global)
      const cfg = loadGuildPaymentConfig(ctx.guildId);
      const privKey = cfg?.tripayPrivateKey || process.env.TRIPAY_PRIVATE_KEY;
      if (!verifyTripaySignature(req.rawBody, signature, privKey)) {
        console.warn(`[webhook] tripay BAD SIGNATURE ref=${merchantRef}`);
        return res.status(401).json({ error: 'invalid signature' });
      }

      if (status === 'PAID') {
        // V2: amount diverifikasi di processOrderPaid (expectedAmount)
        const result = await processOrderPaid(clientFor(ctx.ownerUserId), merchantRef, amount);
        console.log(`[webhook] tripay PAID ref=${merchantRef}:`, result);
      }
      res.json({ success: true });
    } catch (e) {
      console.error('[webhook] tripay error:', e.message);
      res.status(500).json({ error: 'internal' });
    }
  });

  // --- Midtrans webhook (multi-tenant, SHA-512 per spec) ---
  app.post('/webhook/midtrans', async (req, res) => {
    try {
      const b = req.body || {};
      const orderId = b.order_id;
      const ctx = resolveOrderContext(orderId);
      if (!ctx) return res.status(404).json({ error: 'order not found' });

      const cfg = loadGuildPaymentConfig(ctx.guildId);
      const serverKey = cfg?.midtransServerKey;
      if (!verifyMidtransSignature(b, serverKey)) {
        console.warn(`[webhook] midtrans BAD SIGNATURE order=${orderId}`);
        return res.status(401).json({ error: 'invalid signature' });
      }

      // Status lunas Midtrans: settlement / capture(accept)
      const paid = b.transaction_status === 'settlement' ||
        (b.transaction_status === 'capture' && b.fraud_status === 'accept');
      if (paid) {
        const result = await processOrderPaid(clientFor(ctx.ownerUserId), orderId, b.gross_amount);
        console.log(`[webhook] midtrans PAID order=${orderId}:`, result);
      }
      res.json({ success: true });
    } catch (e) {
      console.error('[webhook] midtrans error:', e.message);
      res.status(500).json({ error: 'internal' });
    }
  });

  // --- Pakasir webhook (multi-tenant, verify via transactiondetail API) ---
  app.post('/webhook/pakasir', async (req, res) => {
    try {
      const orderId = req.body?.order_id;
      const amount = req.body?.amount;
      if (!orderId) return res.status(400).json({ error: 'order_id required' });

      const ctx = resolveOrderContext(orderId);
      if (!ctx) return res.status(404).json({ error: 'order not found' });

      const cfg = loadGuildPaymentConfig(ctx.guildId);
      const apiKey = cfg?.pakasirApiKey || process.env.PAKASIR_API_KEY;
      const slug = cfg?.pakasirSlug || process.env.PAKASIR_SLUG;
      if (!apiKey || !slug) {
        console.warn(`[webhook] pakasir NO KEYS for guild=${ctx.guildId}`);
        return res.status(500).json({ error: 'pakasir not configured' });
      }

      const verification = await verifyPakasirCallback(orderId, amount, apiKey, slug);
      if (verification.paid) {
        const result = await processOrderPaid(getUserClient(ctx.ownerUserId), orderId, verification.amount || amount);
        console.log(`[webhook] pakasir PAID order=${orderId}:`, result);
      }
      res.json({ success: true });
    } catch (e) {
      console.error('[webhook] pakasir error:', e.message);
      res.status(500).json({ error: 'internal' });
    }
  });

  // --- Mock pay: HANYA dev (V6: cegah gratisan di produksi) ---
  app.get('/mock-pay', async (req, res) => {
    if (process.env.NODE_ENV !== 'dev' && process.env.ALLOW_MOCK_PAY !== '1') {
      return res.status(403).send('Mock payment disabled in production');
    }
    const invoiceId = req.query.invoice;
    const ctx = resolveOrderContext(invoiceId);
    const expected = ctx?.order?.total; // mock: pakai total order biar V2 tetap lolos
    const result = await processOrderPaid(clientFor(ctx?.ownerUserId), invoiceId, expected);
    res.send(`<html><body style="font-family:sans-serif;padding:40px;">
      <h2>${result.ok ? '✅ Mock Payment Success' : '❌ ' + result.error}</h2>
      <p>Invoice: <code>${invoiceId}</code></p>
      <p>Status: <code>${result.status || result.error}</code></p>
      <p>Cek DM Discord kamu untuk delivery.</p>
    </body></html>`);
  });

  // Dashboard static files
  const publicDir = path.join(__dirname, 'public');

  // Login page (public)
  app.get('/login', (_, res) => res.sendFile(path.join(publicDir, 'login.html')));

  // Landing page (public)
  app.get('/home', (_, res) => res.sendFile(path.join(publicDir, 'landing.html')));

  // Root: landing page if not logged in, redirect to dashboard if logged in
  app.get('/', (req, res) => {
    if (req.user) return res.redirect('/app');
    res.sendFile(path.join(publicDir, 'landing.html'));
  });

  // Dashboard (gated)
  app.get(['/app', '/app/*'], (req, res) => {
    if (!req.user) return res.redirect('/login');
    res.sendFile(path.join(publicDir, 'index.html'));
  });

  // Static assets (index:false biar '/' gak auto-serve index.html tanpa auth)
  app.use('/', express.static(publicDir, { index: false }));

  const port = process.env.WEB_PORT || 4002;
  // Bind ke localhost saja — akses publik HANYA lewat nginx (haikzs.tech / TLS).
  // Ini nutup celah C1: dashboard gak lagi ke-expose plaintext di IP publik.
  app.set('trust proxy', 1); // percaya X-Forwarded-* dari nginx (1 hop)
  app.listen(port, '127.0.0.1', () => console.log(`🌐 Dashboard on http://127.0.0.1:${port} (via nginx: https://haikzs.tech)`));
}
