const express = require('express');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const router = express.Router();
const { getDB } = require('../config/database');
const { smtpTransporter, SMTP_FROM } = require('../config/smtp');
const { auth, createSessionToken, verifySessionToken, JWT_SECRET } = require('../middleware/auth');
const { ok, err, logActivity, paginate, sanitize } = require('../helpers/response');

// List konsultasi (admin + filtered by role)
router.get('/', async (req, res, next) => {
  try {
    const db = getDB();
    const { page = 1, limit = 10, status = '', email = '' } = req.query;
    let where = 'WHERE 1=1'; const params = [];
    if (status) { where += ' AND k.status = ?'; params.push(status); }
    if (email) { where += ' AND k.email = ?'; params.push(email); }

    const token = req.headers.authorization?.split(' ')[1];
    let loggedUser = null;
    if (token) {
      try { loggedUser = jwt.verify(token, JWT_SECRET); } catch { /* ignore */ }
    }
    if (loggedUser && loggedUser.role === 'Ustadz') {
      where += ' AND k.ustadz_id = ?';
      params.push(loggedUser.id);
    }

    const result = await paginate(
      `SELECT k.*, u.nama as ustadz_nama FROM konsultasi k LEFT JOIN users u ON k.ustadz_id = u.id ${where} ORDER BY k.created_at DESC`,
      params, +page, +limit
    );
    // Batch fetch replies (menghindari N+1 query)
    if (result.data.length > 0) {
      const ids = result.data.map(k => k.id);
      const [allReplies] = await db.query('SELECT * FROM konsultasi_reply WHERE konsultasi_id IN (?) ORDER BY created_at ASC', [ids]);
      const repliesMap = {};
      for (const r of allReplies) {
        if (!repliesMap[r.konsultasi_id]) repliesMap[r.konsultasi_id] = [];
        repliesMap[r.konsultasi_id].push(r);
      }
      for (const k of result.data) {
        k.replies = repliesMap[k.id] || [];
      }
    }
    ok(res, result);
  } catch (e) { next(e); }
});

router.get('/pending-count', auth(), async (req, res, next) => {
  try {
    const db = getDB();
    const [rows] = await db.query("SELECT COUNT(*) as c FROM konsultasi WHERE status = 'pending'");
    ok(res, { count: rows[0].c });
  } catch (e) { next(e); }
});

// Public submit question
router.post('/', async (req, res, next) => {
  try {
    const db = getDB();
    const { penanya, email, pertanyaan } = req.body;
    if (!penanya || !pertanyaan) return err(res, 'Nama dan pertanyaan wajib diisi');
    const [result] = await db.query('INSERT INTO konsultasi (penanya, email, pertanyaan) VALUES (?,?,?)', [penanya, email || '', pertanyaan]);
    ok(res, { id: result.insertId }, 'Pertanyaan berhasil dikirim');
  } catch (e) { next(e); }
});

// Admin reply
router.post('/:id/reply', auth(['Admin', 'Ustadz']), async (req, res, next) => {
  try {
    const db = getDB();
    const { id } = req.params;
    const { teks } = req.body;
    if (!teks) return err(res, 'Teks jawaban wajib diisi');
    const [kRows] = await db.query('SELECT * FROM konsultasi WHERE id = ?', [id]);
    if (kRows.length === 0) return err(res, 'Konsultasi tidak ditemukan', 404);
    if (kRows[0].status === 'closed') return err(res, 'Tidak dapat membalas tiket yang sudah ditutup');
    await db.query("INSERT INTO konsultasi_reply (konsultasi_id, dari, nama, teks) VALUES (?,?,?,?)", [id, 'admin', req.user.nama, teks]);
    await db.query("UPDATE konsultasi SET status = 'answered' WHERE id = ?", [id]);
    await logActivity('SUCCESS', `Konsultasi #${id} dijawab`, req.user.id, req.ip);
    ok(res, null, 'Jawaban berhasil dikirim');
  } catch (e) { next(e); }
});

// Update status
router.patch('/:id/status', auth(['Admin', 'Ustadz']), async (req, res, next) => {
  try {
    const db = getDB();
    const { status } = req.body;
    if (!['pending', 'answered', 'closed'].includes(status)) return err(res, 'Status tidak valid');
    await db.query('UPDATE konsultasi SET status = ? WHERE id = ?', [status, req.params.id]);
    ok(res, null, 'Status diperbarui');
  } catch (e) { next(e); }
});

// Delete
router.delete('/:id', auth(['Admin', 'Ustadz']), async (req, res, next) => {
  try {
    const db = getDB();
    const { id } = req.params;
    await db.query('DELETE FROM konsultasi_reply WHERE konsultasi_id = ?', [id]);
    await db.query('DELETE FROM konsultasi WHERE id = ?', [id]);
    await logActivity('SUCCESS', `Konsultasi #${id} dihapus`, req.user.id, req.ip);
    ok(res, null, 'Konsultasi berhasil dihapus');
  } catch (e) { next(e); }
});

// Bulk delete
router.post('/bulk-delete', auth(['Admin', 'Ustadz']), async (req, res, next) => {
  try {
    const db = getDB();
    const { ids } = req.body;
    if (!Array.isArray(ids) || ids.length === 0) return err(res, 'Tidak ada ID yang dipilih');
    await db.query('DELETE FROM konsultasi_reply WHERE konsultasi_id IN (?)', [ids]);
    await db.query('DELETE FROM konsultasi WHERE id IN (?)', [ids]);
    await logActivity('SUCCESS', `Bulk delete konsultasi: ${ids.length} item`, req.user.id, req.ip);
    ok(res, null, `${ids.length} konsultasi berhasil dihapus`);
  } catch (e) { next(e); }
});

// Send OTP
router.post('/send-otp', async (req, res, next) => {
  try {
    const db = getDB();
    const { email } = req.body;
    if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return err(res, 'Email tidak valid');

    const [recent] = await db.query(
      'SELECT COUNT(*) as c FROM otp_codes WHERE email = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)', [email]
    );
    if (recent[0].c >= 3) return err(res, 'Terlalu banyak permintaan OTP. Coba lagi dalam 1 jam.', 429);

    const code = String(crypto.randomInt(100000, 999999));
    const expiresAt = new Date(Date.now() + 10 * 60 * 1000);
    await db.query('INSERT INTO otp_codes (email, code, expires_at) VALUES (?, ?, ?)', [email, code, expiresAt]);

    try {
      await smtpTransporter.sendMail({
        from: `"Nūr Al-'Ilm Konsultasi" <${SMTP_FROM}>`,
        to: email,
        subject: `Kode Verifikasi Konsultasi - ${code}`,
        html: `
          <div style="font-family:Arial,sans-serif;max-width:480px;margin:0 auto;padding:20px">
            <div style="text-align:center;padding:20px;background:linear-gradient(135deg,#0d7c3d,#10a94a);border-radius:12px 12px 0 0">
              <h2 style="color:#fff;margin:0">Nūr Al-'Ilm</h2>
              <p style="color:rgba(255,255,255,.8);margin:4px 0 0">E-Konsultasi Islami</p>
            </div>
            <div style="background:#fff;padding:30px;border:1px solid #e0e0e0;border-top:none;border-radius:0 0 12px 12px">
              <p>Assalamu'alaikum,</p>
              <p>Kode verifikasi Anda untuk mengakses layanan E-Konsultasi:</p>
              <div style="text-align:center;margin:24px 0">
                <div style="display:inline-block;padding:16px 32px;background:#f0faf4;border:2px dashed #0d7c3d;border-radius:12px;font-size:32px;font-weight:bold;letter-spacing:8px;color:#0d7c3d">
                  ${code}
                </div>
              </div>
              <p style="color:#666;font-size:13px">Kode ini berlaku selama <strong>10 menit</strong>. Jangan bagikan kode ini kepada siapapun.</p>
              <hr style="border:none;border-top:1px solid #eee;margin:20px 0">
              <p style="color:#999;font-size:11px;text-align:center">Email ini dikirim otomatis oleh sistem Nūr Al-'Ilm.</p>
            </div>
          </div>
        `
      });
    } catch (mailErr) {
      console.error('SMTP Error:', mailErr.message);
      if (!process.env.SMTP_USER) {
        console.log(`[DEV] OTP for ${email}: ${code}`);
        return ok(res, { dev_mode: true, message: 'SMTP belum dikonfigurasi. Lihat kode OTP di terminal server.' }, 'Kode OTP (dev mode) - lihat terminal server');
      }
      return err(res, 'Gagal mengirim email. Coba lagi nanti.', 500);
    }

    ok(res, null, 'Kode verifikasi telah dikirim ke email Anda');
  } catch (e) { next(e); }
});

// Verify OTP
router.post('/verify-otp', async (req, res, next) => {
  try {
    const db = getDB();
    const { email, code } = req.body;
    if (!email || !code) return err(res, 'Email dan kode OTP wajib diisi');
    const [rows] = await db.query(
      'SELECT * FROM otp_codes WHERE email = ? AND code = ? AND used = FALSE AND expires_at > NOW() ORDER BY created_at DESC LIMIT 1', [email, code]
    );
    if (rows.length === 0) return err(res, 'Kode OTP tidak valid atau sudah kedaluwarsa', 401);
    await db.query('UPDATE otp_codes SET used = TRUE WHERE id = ?', [rows[0].id]);
    await db.query('DELETE FROM otp_codes WHERE expires_at < NOW()');
    const token = createSessionToken(email);
    ok(res, { token, email }, 'Verifikasi berhasil');
  } catch (e) { next(e); }
});

// My history (verified user)
router.get('/my-history', async (req, res, next) => {
  try {
    const db = getDB();
    const authHeader = req.headers.authorization;
    if (!authHeader) return err(res, 'Token diperlukan', 401);
    const token = authHeader.replace('Bearer ', '');
    const session = verifySessionToken(token);
    if (!session) return err(res, 'Sesi tidak valid atau sudah kedaluwarsa', 401);
    const [konsultasi] = await db.query('SELECT * FROM konsultasi WHERE email = ? ORDER BY created_at DESC', [session.email]);
    // Batch fetch replies
    if (konsultasi.length > 0) {
      const ids = konsultasi.map(k => k.id);
      const [allReplies] = await db.query('SELECT * FROM konsultasi_reply WHERE konsultasi_id IN (?) ORDER BY created_at ASC', [ids]);
      const repliesMap = {};
      for (const r of allReplies) {
        if (!repliesMap[r.konsultasi_id]) repliesMap[r.konsultasi_id] = [];
        repliesMap[r.konsultasi_id].push(r);
      }
      for (const k of konsultasi) {
        k.replies = repliesMap[k.id] || [];
      }
    }
    ok(res, { data: konsultasi, email: session.email });
  } catch (e) { next(e); }
});

// Send new ticket (verified user)
router.post('/send', async (req, res, next) => {
  try {
    const db = getDB();
    const authHeader = req.headers.authorization;
    if (!authHeader) return err(res, 'Token diperlukan', 401);
    const token = authHeader.replace('Bearer ', '');
    const session = verifySessionToken(token);
    if (!session) return err(res, 'Sesi tidak valid atau sudah kedaluwarsa', 401);

    const { penanya, pertanyaan, ustadz_id } = req.body;
    if (!penanya || !pertanyaan) return err(res, 'Nama dan pertanyaan wajib diisi');
    const safePenanya = sanitize(penanya.trim());
    const safePertanyaan = sanitize(pertanyaan.trim());

    const [activeTickets] = await db.query("SELECT id FROM konsultasi WHERE email = ? AND status != 'closed'", [session.email]);
    if (activeTickets.length > 0) return err(res, 'Anda masih memiliki tiket konsultasi yang aktif. Harap selesaikan tiket tersebut (tunggu ditutup) sebelum membuat yang baru.', 400);

    const validUstadzId = ustadz_id ? parseInt(ustadz_id) : null;
    if (validUstadzId) {
      const [uCheck] = await db.query('SELECT id FROM users WHERE id = ? AND status = ?', [validUstadzId, 'Aktif']);
      if (uCheck.length === 0) return err(res, 'Ustadz yang dipilih tidak valid');
    }

    const [result] = await db.query('INSERT INTO konsultasi (penanya, email, pertanyaan, ustadz_id) VALUES (?, ?, ?, ?)', [safePenanya, session.email, safePertanyaan, validUstadzId]);
    ok(res, { id: result.insertId }, 'Tiket konsultasi berhasil dibuat');
  } catch (e) { next(e); }
});

// User reply (verified user)
router.post('/:id/user-reply', async (req, res, next) => {
  try {
    const db = getDB();
    const authHeader = req.headers.authorization;
    if (!authHeader) return err(res, 'Token diperlukan', 401);
    const token = authHeader.replace('Bearer ', '');
    const session = verifySessionToken(token);
    if (!session) return err(res, 'Sesi tidak valid atau sudah kedaluwarsa', 401);

    const { id } = req.params;
    const { teks } = req.body;
    if (!teks) return err(res, 'Pesan tidak boleh kosong');
    const [kRows] = await db.query('SELECT * FROM konsultasi WHERE id = ? AND email = ?', [id, session.email]);
    if (kRows.length === 0) return err(res, 'Tiket tidak ditemukan', 404);
    if (kRows[0].status === 'closed') return err(res, 'Tiket sudah ditutup. Buat tiket baru jika ada pertanyaan lain.');

    const safeTeks = sanitize(teks.trim());
    await db.query("INSERT INTO konsultasi_reply (konsultasi_id, dari, nama, teks) VALUES (?, 'user', ?, ?)", [id, kRows[0].penanya, safeTeks]);
    await db.query("UPDATE konsultasi SET status = 'pending' WHERE id = ?", [id]);
    ok(res, null, 'Pesan berhasil dikirim');
  } catch (e) { next(e); }
});

// Rate (verified user)
router.post('/:id/rate', async (req, res, next) => {
  try {
    const db = getDB();
    const authHeader = req.headers.authorization;
    if (!authHeader) return err(res, 'Token diperlukan', 401);
    const token = authHeader.replace('Bearer ', '');
    const session = verifySessionToken(token);
    if (!session) return err(res, 'Sesi tidak valid atau sudah kedaluwarsa', 401);

    const { id } = req.params;
    const { rating, ulasan } = req.body;
    if (!rating || rating < 1 || rating > 5) return err(res, 'Rating tidak valid');
    const [kRows] = await db.query('SELECT * FROM konsultasi WHERE id = ? AND email = ?', [id, session.email]);
    if (kRows.length === 0) return err(res, 'Tiket tidak ditemukan', 404);
    if (kRows[0].status !== 'closed') return err(res, 'Hanya bisa memberikan ulasan pada tiket yang sudah ditutup', 400);
    if (kRows[0].rating !== null) return err(res, 'Anda sudah memberikan ulasan untuk tiket ini', 400);

    const safeUlasan = ulasan ? sanitize(ulasan.trim()) : null;
    await db.query("UPDATE konsultasi SET rating = ?, ulasan = ? WHERE id = ?", [rating, safeUlasan, id]);
    ok(res, null, 'Terima kasih atas penilaian Anda!');
  } catch (e) { next(e); }
});

module.exports = router;
