const express = require("express");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const { v4: uuidv4 } = require("uuid");
const { query, queryOne, insert } = require("../db");
const { notifyNewUser } = require("../telegram");

const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET || JWT_SECRET === "your_super_secret_key_change_this") {
  console.error("⚠️  CRITICAL: JWT_SECRET is not set or using default! Set a strong secret in .env");
}
const EFFECTIVE_JWT_SECRET = JWT_SECRET || require("crypto").randomBytes(32).toString("hex");

// ===== Input Sanitization & Validation =====
function sanitize(str) {
  if (typeof str !== "string") return "";
  return str.replace(/[<>"'&]/g, c => ({
    "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#x27;", "&": "&amp;"
  }[c])).trim();
}

function isValidEmail(email) {
  const re = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/;
  return re.test(email) && email.length <= 254;
}

function isValidUsername(username) {
  const re = /^[a-zA-Z0-9_.\-\u1780-\u17FF]{2,30}$/;
  return re.test(username);
}

// POST /zapi/auth/register
router.post("/register", async (req, res) => {
  try {
    const username = sanitize(req.body.username || "");
    const email = (req.body.email || "").trim().toLowerCase();
    const password = req.body.password || "";
    const telegram = sanitize(req.body.telegram || "");

    if (!username || !email || !password) {
      return res.status(400).json({ message: "សូមបំពេញគ្រប់ field ទាំងអស់" });
    }
    if (!isValidUsername(username)) {
      return res.status(400).json({ message: "Username មិនត្រឹមត្រូវ (2-30 តួអក្សរ, a-z, 0-9, _, -, .)" });
    }
    if (!isValidEmail(email)) {
      return res.status(400).json({ message: "Email មិនត្រឹមត្រូវ" });
    }
    if (password.length < 6 || password.length > 128) {
      return res.status(400).json({ message: "ពាក្យសម្ងាត់ត្រូវមាន 6-128 តួអក្សរ" });
    }

    // Check duplicates
    const existingEmail = await queryOne("SELECT id FROM users WHERE email = ?", [email]);
    if (existingEmail) {
      return res.status(409).json({ message: "Email នេះមានរួចហើយ" });
    }

    const existingUsername = await queryOne("SELECT id FROM users WHERE username = ?", [username]);
    if (existingUsername) {
      return res.status(409).json({ message: "Username នេះមានរួចហើយ" });
    }

    const hashedPassword = await bcrypt.hash(password, 10);
    const newUser = {
      id: uuidv4(),
      username,
      email,
      telegram: telegram || "",
      password: hashedPassword,
      balance: 0,
      apiKey: "za_" + uuidv4().replace(/-/g, ""),
      createdAt: new Date().toISOString(),
    };

    await insert(
      `INSERT INTO users (id, username, email, telegram, password, balance, apiKey, createdAt)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
      [newUser.id, newUser.username, newUser.email, newUser.telegram, newUser.password, newUser.balance, newUser.apiKey, new Date()]
    );

    // Notify admin via Telegram
    notifyNewUser(newUser);

    res.status(201).json({ message: "គណនីបង្កើតរួច", userId: newUser.id });
  } catch (err) {
    console.error("[Auth Register]", err.message);
    res.status(500).json({ message: "Server error" });
  }
});

// ═══════════════════════════════════════════════════════════
// 🛡️ LOGIN ATTEMPT TRACKING — ការពារ brute force
// ═══════════════════════════════════════════════════════════
const loginAttempts = new Map();
const MAX_LOGIN_ATTEMPTS = 5;
const LOCK_DURATION = 15 * 60 * 1000;

function checkLoginLock(key) {
  const record = loginAttempts.get(key);
  if (!record) return false;
  if (record.lockedUntil && Date.now() < record.lockedUntil) {
    const remaining = Math.ceil((record.lockedUntil - Date.now()) / 60000);
    return remaining;
  }
  if (record.lockedUntil && Date.now() >= record.lockedUntil) {
    loginAttempts.delete(key);
  }
  return false;
}

function recordFailedLogin(key) {
  const record = loginAttempts.get(key) || { count: 0, lockedUntil: null };
  record.count++;
  if (record.count >= MAX_LOGIN_ATTEMPTS) {
    record.lockedUntil = Date.now() + LOCK_DURATION;
    console.log(`🔒 [Security] Account locked: ${key} (${record.count} failed attempts)`);
  }
  loginAttempts.set(key, record);
}

function clearLoginAttempts(key) {
  loginAttempts.delete(key);
}

// POST /zapi/auth/login
router.post("/login", async (req, res) => {
  try {
    const email = (req.body.email || "").trim();
    const password = req.body.password || "";

    if (!email || !password) {
      return res.status(400).json({ message: "សូមបំពេញ email និង password" });
    }
    if (email.length > 254 || password.length > 128) {
      return res.status(400).json({ message: "Input មិនត្រឹមត្រូវ" });
    }

    // 🛡️ Check if account is locked for this IP
    const ip = req.ip || req.connection.remoteAddress;
    const lockKey = `${ip}_${email.toLowerCase()}`;
    const lockMinutes = checkLoginLock(lockKey);
    if (lockMinutes) {
      return res.status(429).json({
        message: `គណនីត្រូវបានចាក់សោ — សូមរង់ចាំ ${lockMinutes} នាទី`
      });
    }

    const user = await queryOne(
      "SELECT * FROM users WHERE email = ? OR username = ? LIMIT 1",
      [email, email]
    );

    if (!user) {
      recordFailedLogin(lockKey);
      return res.status(401).json({ message: "Email ឬ Password មិនត្រឹមត្រូវ" });
    }

    const valid = await bcrypt.compare(password, user.password);
    if (!valid) {
      recordFailedLogin(lockKey);
      return res.status(401).json({ message: "Email ឬ Password មិនត្រឹមត្រូវ" });
    }

    // 🛡️ Login success — clear failed attempts
    clearLoginAttempts(lockKey);

    const token = jwt.sign({ id: user.id, email: user.email }, EFFECTIVE_JWT_SECRET, { expiresIn: "7d" });

    res.json({
      token,
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        balance: parseFloat(user.balance),
        apiKey: user.apiKey,
        role: user.role || "user",
      },
    });
  } catch (err) {
    console.error("[Auth Login]", err.message);
    res.status(500).json({ message: "Server error" });
  }
});

// GET /zapi/auth/me — Get current user data
router.get("/me", async (req, res) => {
  try {
    const authHeader = req.headers.authorization;
    if (!authHeader) return res.status(401).json({ message: "No token" });
    const token = authHeader.replace("Bearer ", "");
    const decoded = jwt.verify(token, EFFECTIVE_JWT_SECRET);
    const user = await queryOne("SELECT id, username, email, balance, role FROM users WHERE id = ?", [decoded.id]);
    if (!user) return res.status(404).json({ message: "User not found" });
    res.json({
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        balance: parseFloat(user.balance),
        role: user.role || "user"
      }
    });
  } catch (err) {
    res.status(401).json({ message: "Invalid token" });
  }
});

// POST /zapi/auth/forgot — Send reset link via Telegram
router.post("/forgot", async (req, res) => {
  try {
    const { email } = req.body;
    if (!email) {
      return res.status(400).json({ message: "សូមបញ្ចូល email" });
    }

    const user = await queryOne("SELECT * FROM users WHERE email = ?", [email]);
    if (!user) {
      return res.status(404).json({ message: "រកមិនឃើញ email នេះក្នុងប្រព័ន្ធ" });
    }

    // Generate reset token
    const resetToken = jwt.sign({ id: user.id, type: "reset" }, EFFECTIVE_JWT_SECRET, { expiresIn: "15m" });

    const { notifyPasswordReset } = require("../telegram");
    if (notifyPasswordReset) {
      notifyPasswordReset(user, resetToken);
    }

    res.json({ message: "Reset link ត្រូវបានផ្ញើទៅ Telegram របស់អ្នក" });
  } catch (err) {
    console.error("[Auth Forgot]", err.message);
    res.status(500).json({ message: "Server error" });
  }
});

// POST /zapi/auth/reset — Submit new password with reset token
router.post("/reset", async (req, res) => {
  try {
    const { token, password } = req.body;
    if (!token || !password) {
      return res.status(400).json({ message: "សូមបំពេញពាក្យសម្ងាត់ថ្មី" });
    }
    if (password.length < 6 || password.length > 128) {
      return res.status(400).json({ message: "ពាក្យសម្ងាត់ត្រូវមាន 6-128 តួអក្សរ" });
    }

    let decoded;
    try {
      decoded = jwt.verify(token, EFFECTIVE_JWT_SECRET);
    } catch (err) {
      return res.status(401).json({ message: "Token ផុតកំណត់ ឬមិនត្រឹមត្រូវ" });
    }

    if (decoded.type !== "reset") {
      return res.status(401).json({ message: "Token មិនត្រឹមត្រូវ" });
    }

    const user = await queryOne("SELECT id FROM users WHERE id = ?", [decoded.id]);
    if (!user) {
      return res.status(404).json({ message: "រកមិនឃើញគណនីនេះក្នុងប្រព័ន្ធ" });
    }

    const hashedPassword = await bcrypt.hash(password, 10);
    await query("UPDATE users SET password = ? WHERE id = ?", [hashedPassword, decoded.id]);

    res.json({ message: "ពាក្យសម្ងាត់ត្រូវបានផ្លាស់ប្ដូរដោយជោគជ័យ" });
  } catch (err) {
    res.status(500).json({ message: "Server error", error: err.message });
  }
});

// GET /zapi/auth/google — Google OAuth redirect
router.get("/google", (req, res) => {
  const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
  const REDIRECT_URI = process.env.GOOGLE_REDIRECT_URI || `http://localhost:${process.env.PORT || 3000}/zapi/auth/google/callback`;

  if (!GOOGLE_CLIENT_ID) {
    return res.status(501).json({ message: "Google OAuth មិនទាន់បានកំណត់ — សូមដាក់ GOOGLE_CLIENT_ID ក្នុង .env" });
  }

  const url = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${GOOGLE_CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&response_type=code&scope=email%20profile&access_type=offline`;
  res.redirect(url);
});

// GET /zapi/auth/google/callback — Google OAuth callback
router.get("/google/callback", async (req, res) => {
  const { code } = req.query;
  const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
  const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
  const REDIRECT_URI = process.env.GOOGLE_REDIRECT_URI || `http://localhost:${process.env.PORT || 3000}/zapi/auth/google/callback`;

  if (!code || !GOOGLE_CLIENT_ID || !GOOGLE_CLIENT_SECRET) {
    return res.redirect("/login?error=google_failed");
  }

  try {
    // Exchange code for tokens
    const tokenRes = await fetch("https://oauth2.googleapis.com/token", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        code,
        client_id: GOOGLE_CLIENT_ID,
        client_secret: GOOGLE_CLIENT_SECRET,
        redirect_uri: REDIRECT_URI,
        grant_type: "authorization_code",
      }),
    });
    const tokenData = await tokenRes.json();

    if (!tokenData.access_token) {
      return res.redirect("/login?error=google_failed");
    }

    // Get user info from Google
    const userRes = await fetch("https://www.googleapis.com/oauth2/v2/userinfo", {
      headers: { Authorization: `Bearer ${tokenData.access_token}` },
    });
    const googleUser = await userRes.json();

    // Find or create user
    let user = await queryOne("SELECT * FROM users WHERE email = ?", [googleUser.email]);

    if (!user) {
      // Create new user from Google
      const newUser = {
        id: uuidv4(),
        username: googleUser.name || googleUser.email.split("@")[0],
        email: googleUser.email,
        telegram: "",
        password: await bcrypt.hash(uuidv4(), 10),
        balance: 0,
        apiKey: "za_" + uuidv4().replace(/-/g, ""),
        googleId: googleUser.id,
      };

      await insert(
        `INSERT INTO users (id, username, email, telegram, password, balance, apiKey, googleId, createdAt)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
        [newUser.id, newUser.username, newUser.email, newUser.telegram, newUser.password, newUser.balance, newUser.apiKey, newUser.googleId]
      );

      user = newUser;
      notifyNewUser(newUser);
    }

    // Generate JWT
    const token = jwt.sign({ id: user.id, email: user.email }, EFFECTIVE_JWT_SECRET, { expiresIn: "7d" });

    res.redirect(`/login?token=${token}&user=${encodeURIComponent(JSON.stringify({
      id: user.id,
      username: user.username,
      email: user.email,
      balance: parseFloat(user.balance),
      apiKey: user.apiKey,
      role: user.role || "user",
    }))}`);
  } catch (err) {
    console.error("[Google OAuth] Error:", err.message);
    res.redirect("/login?error=google_failed");
  }
});

module.exports = router;
