const express = require("express");
const jwt = require("jsonwebtoken");
const { BakongKHQR, IndividualInfo, khqrData } = require("bakong-khqr");
const QRCode = require("qrcode");
const { query, queryOne, insert, transaction } = require("../db");
const { notifyPaymentCompleted, notifyPaymentStarted, notifyPaymentTailNumber } = require("../telegram");

const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET || require("crypto").randomBytes(32).toString("hex");

// Bakong config
const BAKONG_TOKEN = process.env.BAKONG_TOKEN;
const BAKONG_ACCOUNT_ID = process.env.BAKONG_ACCOUNT;
const BAKONG_MERCHANT_NAME = process.env.BAKONG_NAME || "Merchant";
const BAKONG_CITY = process.env.BAKONG_CITY || "Phnom Penh";

if (!BAKONG_TOKEN || !BAKONG_ACCOUNT_ID) {
  console.error("⚠️  BAKONG_TOKEN or BAKONG_ACCOUNT not set in .env — payments will fail");
} else {
  console.log("✅ BAKONG_TOKEN loaded (expires check needed)");
  console.log("   Token starts with:", BAKONG_TOKEN.substring(0, 30) + "...");
  console.log("   Account:", BAKONG_ACCOUNT_ID);
}

/**
 * Check payment via Bakong Open API
 * Tries multiple methods to verify payment status
 */
async function checkBakongPayment(md5Hash) {
  // Method 1: Bakong Open API (official)
  try {
    const res = await fetch("https://api-bakong.nbc.gov.kh/v1/check_transaction_by_md5", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${BAKONG_TOKEN}`,
      },
      body: JSON.stringify({ md5: md5Hash }),
    });

    if (res.ok) {
      const data = await res.json();
      console.log("[Payment Check] Bakong API response:", JSON.stringify(data));
      if (data && data.responseCode === 0 && data.data && (data.data.hash || data.data.status === "SUCCESS" || data.data.fromAccountId || (typeof data.data === "object" && Object.keys(data.data).length > 0 && data.data.status !== "PENDING" && data.data.status !== "FAILED"))) {
        return { paid: true, source: "bakong-api", data: data.data };
      }
      console.log("[Payment Check] Bakong API returned unpaid/pending, falling back...");
    } else {
      const errText = await res.text();
      console.log(`[Payment Check] Bakong API HTTP ${res.status}:`, errText);
    }
  } catch (e) {
    console.log("[Payment Check] Bakong API error:", e.message);
  }

  // Method 2: Fallback via mmotool.dev
  try {
    const res = await fetch(`https://mmotool.dev/check_payment.php?md5=${encodeURIComponent(md5Hash)}`);
    if (res.ok) {
      const data = await res.json();
      console.log("[Payment Check] mmotool response:", JSON.stringify(data));
      if (data && (data.status === "PAID" || data.status === "SUCCESS" || data.status === "success" || data.paid === true || data.result === true || (data.responseCode === 0 && data.data))) {
        return { paid: true, source: "mmotool", data };
      }
      return { paid: false, source: "mmotool", detail: data };
    }
    console.log(`[Payment Check] mmotool HTTP ${res.status}`);
  } catch (e) {
    console.log("[Payment Check] mmotool error:", e.message);
  }

  // Method 3: Fallback via Bakong SIT API (testing environment)
  try {
    const res = await fetch("https://sit-api-bakong.nbc.gov.kh/v1/check_transaction_by_md5", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${BAKONG_TOKEN}`,
      },
      body: JSON.stringify({ md5: md5Hash }),
    });

    if (res.ok) {
      const data = await res.json();
      console.log("[Payment Check] Bakong SIT API response:", JSON.stringify(data));
      if (data && data.responseCode === 0 && data.data && (data.data.hash || data.data.status === "SUCCESS" || data.data.fromAccountId || (typeof data.data === "object" && Object.keys(data.data).length > 0 && data.data.status !== "PENDING" && data.data.status !== "FAILED"))) {
        return { paid: true, source: "bakong-sit", data: data.data };
      }
    }
  } catch (e) {
    console.log("[Payment Check] Bakong SIT error:", e.message);
  }

  return { paid: false, source: "all-failed" };
}

// Auth middleware
async function auth(req, res, next) {
  const header = req.headers.authorization;
  if (!header) return res.status(401).json({ message: "No token" });
  const token = header.replace("Bearer ", "");
  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    const user = await queryOne("SELECT * FROM users WHERE id = ?", [decoded.id]);
    if (!user) return res.status(404).json({ message: "User not found" });
    req.user = user;
    req.user.balance = parseFloat(user.balance);
    next();
  } catch {
    res.status(401).json({ message: "Invalid token" });
  }
}

/**
 * POST /zapi/payment/khqr
 * Generate Bakong KHQR QR code with amount
 */
router.post("/khqr", auth, async (req, res) => {
  try {
    const { amount } = req.body;
    const amt = parseFloat(amount);

    if (!amt || amt < 2) {
      return res.status(400).json({ message: "ចំនួនទឹកប្រាក់ត្រូវចាប់ពី $2 ឡើងទៅ" });
    }

    const info = new IndividualInfo(BAKONG_ACCOUNT_ID, BAKONG_MERCHANT_NAME, BAKONG_CITY);
    info.currency = khqrData.currency.usd;
    info.amount = amt;
    info.expirationTimestamp = String(Date.now() + 15 * 60 * 1000);

    const bakong = new BakongKHQR(BAKONG_TOKEN);
    const result = bakong.generateIndividual(info);

    if (!result || result.status.code !== 0 || !result.data) {
      console.error("[KHQR]", result ? result.status : "null result");
      return res.status(500).json({ message: "មិនអាចបង្កើត QR code បាន — " + (result ? result.status.message : "unknown") });
    }

    const qrString = result.data.qr;
    const md5 = result.data.md5;
    
    // Generate Base64 QR Code using 'qrcode' library for native download support (No CORS issues)
    const qrImageUrl = await QRCode.toDataURL(qrString, {
      margin: 1,
      width: 400,
      color: {
        dark: '#000000',
        light: '#ffffff'
      }
    });

    // Save pending payment to MySQL
    await insert(
      `INSERT INTO payments (id, userId, username, amount, status, createdAt)
       VALUES (?, ?, ?, ?, 'pending', ?)`,
      [md5, req.user.id, req.user.username, amt, new Date()]
    );

    // Notify Telegram Admin for Manual Approval
    notifyPaymentStarted(
      { id: md5, amount: amt, username: req.user.username },
      req.user
    );

    res.json({
      qrCode: qrImageUrl,
      md5,
      amount: amt,
      expiresIn: 15,
      merchantName: BAKONG_MERCHANT_NAME,
      message: `ស្កេន QR ដើម្បីបង់ $${amt.toFixed(2)}`,
    });
  } catch (err) {
    console.error("[KHQR Generate]", err.message);
    res.status(500).json({ message: "មិនអាចបង្កើត QR code បាន — សូមព្យាយាមម្ដងទៀត" });
  }
});

/**
 * POST /zapi/payment/check
 * Auto-check payment status via Bakong
 */
router.post("/check", auth, async (req, res) => {
  try {
    const { md5 } = req.body;
    if (!md5) return res.status(400).json({ message: "Missing md5" });

    const payment = await queryOne(
      "SELECT * FROM payments WHERE id = ? AND userId = ?",
      [md5, req.user.id]
    );
    if (!payment) return res.status(404).json({ message: "Payment not found" });

    if (payment.status === "completed") {
      return res.json({ status: "completed", message: "បានបង់រួចហើយ ✅", newBalance: req.user.balance });
    }

    // Check if expired (15 min)
    const created = new Date(payment.createdAt).getTime();
    if (Date.now() - created > 15 * 60 * 1000) {
      await query("UPDATE payments SET status = 'expired' WHERE id = ?", [md5]);
      return res.json({ status: "expired", message: "QR ផុតកំណត់ហើយ (15 នាទី) — សូមបង្កើតថ្មី" });
    }

    // Check payment status via Bakong
    const checkResult = await checkBakongPayment(md5);
    console.log(`[Payment Check] md5=${md5}, result:`, JSON.stringify(checkResult));
    const paid = checkResult.paid;

    if (paid) {
      // Use transaction to safely update payment + balance
      const newBalance = await transaction(async (conn) => {
        const [updateResult] = await conn.execute(
          "UPDATE payments SET status = 'completed', paidAt = ? WHERE id = ? AND status = 'pending'",
          [new Date(), md5]
        );
        if (updateResult.affectedRows === 0) {
          throw new Error("ALREADY_COMPLETED");
        }
        await conn.execute(
          "UPDATE users SET balance = balance + ? WHERE id = ?",
          [parseFloat(payment.amount), payment.userId]
        );
        const [rows] = await conn.execute("SELECT balance FROM users WHERE id = ?", [payment.userId]);
        return parseFloat(rows[0].balance);
      });

      // Notify admin via Telegram
      notifyPaymentCompleted(
        { ...payment, status: "completed", paidAt: new Date().toISOString(), amount: parseFloat(payment.amount) },
        { ...req.user, balance: newBalance }
      );

      return res.json({
        status: "completed",
        message: `បានបន្ថែម $${parseFloat(payment.amount).toFixed(3)} ✅`,
        newBalance,
      });
    }

    // Calculate remaining time
    const elapsed = Math.floor((Date.now() - created) / 1000);
    const remaining = Math.max(0, 15 * 60 - elapsed);
    const mins = Math.floor(remaining / 60);
    const secs = remaining % 60;

    res.json({
      status: "pending",
      message: `មិនទាន់ទទួលបានការបង់ប្រាក់ — នៅសល់ ${mins}:${String(secs).padStart(2, "0")} នាទី`,
      remainingSeconds: remaining,
    });
  } catch (err) {
    if (err.message === "ALREADY_COMPLETED") {
      return res.json({ status: "completed", message: "បានបង់រួចហើយ ✅", newBalance: req.user.balance });
    }
    console.error("[KHQR Check]", err.message);
    res.status(500).json({ message: "Server error — សូមព្យាយាមម្ដងទៀត" });
  }
});

/**
 * POST /zapi/payment/submit-tail
 * Submit tail number for manual verification
 */
router.post("/submit-tail", auth, async (req, res) => {
  try {
    const { md5, tail } = req.body;
    if (!md5 || !tail) return res.status(400).json({ message: "Missing required fields" });

    const payment = await queryOne(
      "SELECT * FROM payments WHERE id = ? AND userId = ?",
      [md5, req.user.id]
    );
    if (!payment) return res.status(404).json({ message: "Payment not found" });
    if (payment.status === "completed") return res.status(400).json({ message: "Payment already completed" });

    // Notify Telegram Admin with the tail number
    let meta = {}; try { meta = JSON.parse(payment.username); } catch(e) {}
    notifyPaymentTailNumber(
      { id: md5, amount: parseFloat(payment.amount), username: (meta.purpose === 'api' ? payment.username : req.user.username) },
      req.user,
      tail
    );

    res.json({ status: "success", message: "បានបញ្ជូនលេខកន្ទុយទៅកាន់ Admin" });
  } catch (err) {
    console.error("[Submit-Tail]", err.message);
    res.status(500).json({ message: "Server error" });
  }
});

/**
 * GET /zapi/payment/debug-check/:md5
 * Debug endpoint — test payment check manually (admin only)
 */
router.get("/debug-check/:md5", auth, async (req, res) => {
  try {
    const result = await checkBakongPayment(req.params.md5);
    res.json({ md5: req.params.md5, ...result });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// GET /zapi/payment/history
router.get("/history", auth, async (req, res) => {
  try {
    const payments = await query(
      "SELECT * FROM payments WHERE userId = ? ORDER BY createdAt DESC LIMIT 100",
      [req.user.id]
    );
    res.json(payments.map(p => ({ ...p, amount: parseFloat(p.amount) })));
  } catch (err) {
    console.error("[Payment History]", err.message);
    res.json([]);
  }
});


const API_BASE_URL = "https://za-tool-kh.com/api/";
const ADMIN_SECRET = "Admin1688";
const PRICE_PER_ACCOUNT = 0.012; // 1000 accounts = $12

// Auto-create user_api_keys table
(async () => {
  try {
    await query(`CREATE TABLE IF NOT EXISTS user_api_keys (
      id INT AUTO_INCREMENT PRIMARY KEY,
      userId INT NOT NULL,
      api_key VARCHAR(100) NOT NULL,
      type ENUM('buy_new','topup') DEFAULT 'buy_new',
      amount_paid DECIMAL(10,2) DEFAULT 0,
      credit DECIMAL(10,2) DEFAULT 0,
      note VARCHAR(255) DEFAULT 'Outlook & Hotmail by ZA-FARM',
      createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      INDEX(userId)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`);
    console.log("✅ user_api_keys table ready");
  } catch(e) { console.warn("⚠️ user_api_keys table:", e.message); }

  // Ensure payments table has new_key column (safe migration)
  try {
    await query(`ALTER TABLE payments ADD COLUMN new_key VARCHAR(100) DEFAULT NULL`);
    console.log("✅ payments.new_key column added");
  } catch(e) {
    if (e.message && e.message.toLowerCase().includes("duplicate column")) {
      console.log("✅ payments.new_key column already exists");
    } else {
      console.warn("⚠️ payments.new_key migration:", e.message);
    }
  }
})();


function httpsGet(url) {
  const https = require("https");
  return new Promise((resolve, reject) => {
    const req = https.get(url, { timeout: 8000 }, (res) => {
      let d = ""; res.on("data", c => d += c);
      res.on("end", () => { try { resolve(JSON.parse(d)); } catch { resolve(d); } });
    });
    req.on("timeout", () => { req.destroy(); reject(new Error("timeout")); });
    req.on("error", reject);
  });
}

/**
 * POST /zapi/payment/khqr-api
 * Generate KHQR for API top-up or buy-new (min $3, 1:1 credit)
 * body: { amount, type: 'topup'|'buy_new', api_key? }
 */
router.post("/khqr-api", auth, async (req, res) => {
  try {
    const { amount, type, api_key } = req.body;
    const amt = parseFloat(amount);
    if (!amt || amt < 3) return res.status(400).json({ message: "ចំនួនទឹកប្រាក់ត្រូវចាប់ពី $3 ឡើងទៅ" });
    if (!["topup", "buy_new"].includes(type)) return res.status(400).json({ message: "type មិនត្រឹមត្រូវ" });
    if (type === "topup" && !api_key) return res.status(400).json({ message: "តម្រូវឱ្យបញ្ចូល API Key" });

    const info = new IndividualInfo(BAKONG_ACCOUNT_ID, BAKONG_MERCHANT_NAME, BAKONG_CITY);
    info.currency = khqrData.currency.usd;
    info.amount = amt;
    info.expirationTimestamp = String(Date.now() + 15 * 60 * 1000);
    const bakong = new BakongKHQR(BAKONG_TOKEN);
    const result = bakong.generateIndividual(info);
    if (!result || result.status.code !== 0 || !result.data) {
      return res.status(500).json({ message: "មិនអាចបង្កើត QR code — " + (result?.status?.message || "unknown") });
    }
    const qrString = result.data.qr;
    const md5 = result.data.md5;
    const qrImageUrl = await QRCode.toDataURL(qrString, { margin: 1, width: 400, color: { dark: "#000000", light: "#ffffff" } });

    // Save to payments table with extra metadata in username field as JSON tag
    const meta = JSON.stringify({ purpose: "api", type, api_key: api_key || null });
    await insert(
      `INSERT INTO payments (id, userId, username, amount, status, createdAt) VALUES (?, ?, ?, ?, 'pending', ?)`,
      [md5, req.user.id, meta, amt, new Date()]
    );

    // Notify Telegram Admin for Manual Approval
    notifyPaymentStarted(
      { id: md5, amount: amt, username: meta },
      req.user
    );

    res.json({ qrCode: qrImageUrl, md5, amount: amt, expiresIn: 15, merchantName: BAKONG_MERCHANT_NAME });
  } catch (err) {
    console.error("[KHQR-API Generate]", err.message);
    res.status(500).json({ message: "មិនអាចបង្កើត QR code — សូមព្យាយាមម្ដងទៀត" });
  }
});

/**
 * POST /zapi/payment/check-api
 * Check KHQR payment for API topup and credit API key
 */
router.post("/check-api", auth, async (req, res) => {
  try {
    const { md5 } = req.body;
    if (!md5) return res.status(400).json({ message: "Missing md5" });

    const payment = await queryOne("SELECT * FROM payments WHERE id = ? AND userId = ?", [md5, req.user.id]);
    if (!payment) return res.status(404).json({ message: "Payment not found" });
    if (payment.status === "completed") {
      let meta = {}; try { meta = JSON.parse(payment.username); } catch {}
      return res.json({ status: "completed", type: meta.type, api_key: meta.api_key, amount: parseFloat(payment.amount), new_key: payment.new_key || null });
    }

    const created = new Date(payment.createdAt).getTime();
    if (Date.now() - created > 15 * 60 * 1000) {
      await query("UPDATE payments SET status = 'expired' WHERE id = ?", [md5]);
      return res.json({ status: "expired", message: "QR ផុតកំណត់ (15 នាទី) — សូមបង្កើតថ្មី" });
    }

    const checkResult = await checkBakongPayment(md5);
    if (checkResult.paid) {
      // Prevent race conditions: Atomically transition status from pending
      const [updateResult] = await query("UPDATE payments SET status = 'completed', paidAt = ? WHERE id = ? AND status = 'pending'", [new Date(), md5]);
      if (updateResult.affectedRows === 0) {
        // Already processed by a concurrent request
        let meta = {}; try { meta = JSON.parse(payment.username); } catch {}
        return res.json({ status: "completed", type: meta.type, api_key: meta.api_key, amount: parseFloat(payment.amount), new_key: payment.new_key || null });
      }

      let meta = {}; try { meta = JSON.parse(payment.username); } catch {}
      const amt = parseFloat(payment.amount);

      if (meta.type === "topup") {
        // Top up existing API key
        // 1. Fetch current balance from upstream API
        const balRes = await httpsGet(`${API_BASE_URL}?action=balance&api_key=${encodeURIComponent(meta.api_key)}&_t=${Date.now()}`);
        
        // Strict Validation: If we cannot fetch the old balance, ABORT to prevent wiping it out!
        if (!balRes || balRes.status !== "success" || balRes.balance === undefined) {
          await query("UPDATE payments SET status = 'pending', paidAt = NULL WHERE id = ?", [md5]);
          return res.json({ status: "paid_error", message: "ប្រព័ន្ធរអាក់រអួល មិនអាចអាប់ដេតលុយបាន — សូមរង់ចាំបន្តិច" });
        }
        
        const currentBalance = parseFloat(balRes.balance) || 0;
        
        // 3. Update upstream API with the sum
        const updateRes = await httpsGet(`${API_BASE_URL}?action=admin_topup_user&admin_key=${ADMIN_SECRET}&user_key=${encodeURIComponent(meta.api_key)}&amount=${amt}&_t=${Date.now()}`);
        
        if (updateRes && updateRes.status === "success") {
          // Save top-up record
          await insert(`INSERT INTO user_api_keys (userId, api_key, type, amount_paid, credit, note) VALUES (?, ?, 'topup', ?, ?, 'Outlook & Hotmail Top Up')`, [req.user.id, meta.api_key, amt, amt]);
          return res.json({ status: "completed", type: "topup", api_key: meta.api_key, amount: amt, accounts: Math.floor(amt / PRICE_PER_ACCOUNT) });
        } else {
          // Revert if API failed
          await query("UPDATE payments SET status = 'pending', paidAt = NULL WHERE id = ?", [md5]);
          return res.json({ status: "paid_error", message: "ប្រព័ន្ធរអាក់រអួល មិនអាចអាប់ដេតលុយបាន — សូមរង់ចាំបន្តិច" });
        }
      } else {
        // Buy new API key
        const crypto = require("crypto");
        const newKey = "ZA-" + crypto.randomBytes(10).toString("hex").toUpperCase();
        const createData = await httpsGet(`${API_BASE_URL}?action=admin_add_user&admin_key=${ADMIN_SECRET}&new_user_key=${encodeURIComponent(newKey)}&amount=${amt}&_t=${Date.now()}`);
        if (createData?.status === "success") {
          // Save new key to user's account
          await insert(`INSERT INTO user_api_keys (userId, api_key, type, amount_paid, credit, note) VALUES (?, ?, 'buy_new', ?, ?, 'Outlook & Hotmail New Key')`, [req.user.id, newKey, amt, amt]);
          // Save the generated key to the payment record for future reference
          await query("UPDATE payments SET new_key = ? WHERE id = ?", [newKey, md5]);
          return res.json({ status: "completed", type: "buy_new", new_key: newKey, amount: amt, accounts: Math.floor(amt / PRICE_PER_ACCOUNT) });
        }
        
        // If external API fails, revert the status back to pending so it can be retried
        await query("UPDATE payments SET status = 'pending' WHERE id = ?", [md5]);
        return res.json({ status: "paid_error", message: "បង្កើត Key មានបញ្ហា — ទំនាក់ @za_farm_support_3337" });
      }
    }

    const elapsed = Math.floor((Date.now() - new Date(payment.createdAt).getTime()) / 1000);
    const remaining = Math.max(0, 15 * 60 - elapsed);
    res.json({ status: "pending", message: `រង់ចាំការទូទាត់ — នៅសល់ ${Math.floor(remaining/60)}:${String(remaining%60).padStart(2,"0")} នាទី`, remainingSeconds: remaining });
  } catch (err) {
    console.error("[Check-API]", err.message);
    res.status(500).json({ message: "Server error" });
  }
});

/**
 * GET /zapi/payment/my-api-keys
 * Get all API keys saved for the logged-in user
 */
router.get("/my-api-keys", auth, async (req, res) => {
  try {
    const keys = await query(
      "SELECT * FROM user_api_keys WHERE userId = ? ORDER BY createdAt DESC",
      [req.user.id]
    );
    res.json(keys.map(k => ({
      id: k.id,
      api_key: k.api_key,
      type: k.type,
      amount_paid: parseFloat(k.amount_paid),
      credit: parseFloat(k.credit),
      accounts: Math.floor(parseFloat(k.credit) / PRICE_PER_ACCOUNT),
      note: k.note,
      createdAt: k.createdAt
    })));
  } catch(e) {
    console.error("[my-api-keys]", e.message);
    res.json([]);
  }
});

module.exports = router;
