/**
 * 光湖 · Outline 邮箱注册服务 v1.1
 * BS-SG-001 · 铸渊 ICE-GL-ZY001 · D135c
 * 
 * 修复: SQLite WAL模式 + busy_timeout, 解决Dex并发写入冲突
 */
const express = require('express');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const bcrypt = require('bcryptjs');
const { execSync } = require('child_process');

const app = express();
app.use(express.json());

const PORT = process.env.PORT || 3997;
const DEX_DB_HOST = '/opt/outline/dex-data/dex.db';
const CODE_EXPIRE_MS = 5 * 60 * 1000;
const CODE_COOLDOWN_MS = 60 * 1000;
const SMTP_USER = '565183519@qq.com';
const SMTP_PASS = 'ggeuegmaragmbejb';

const codes = new Map();

let transporter = null;
function getTransporter() {
  if (transporter) return transporter;
  transporter = nodemailer.createTransport({
    host: 'smtp.qq.com', port: 465, secure: true,
    auth: { user: SMTP_USER, pass: SMTP_PASS }
  });
  return transporter;
}

setInterval(() => {
  const now = Date.now();
  for (const [k, v] of codes) {
    if (now - v.ts > CODE_EXPIRE_MS) codes.delete(k);
  }
}, 10 * 60 * 1000);

function hashEmail(email) {
  return crypto.createHash('sha256').update(email.trim().toLowerCase()).digest('hex').slice(0, 16);
}

function generateCode() {
  return String(Math.floor(100000 + Math.random() * 900000));
}

function addUserToDex(email, hash, username, userId) {
  return new Promise((resolve, reject) => {
    try {
      const result = execSync(
        `python3 /opt/zhuyuan/register/add_dex_user.py "${email}" "${hash}" "${username}" "${userId}"`,
        { encoding: 'utf8', timeout: 10000 }
      ).trim();
      if (result === 'EMAIL_EXISTS') return reject(new Error('EMAIL_EXISTS'));
      if (result === 'OK') return resolve(userId);
      reject(new Error('DB_ERROR: ' + result));
    } catch (err) {
      reject(err);
    }
  });
}

app.post('/send-code', async (req, res) => {
  const { email } = req.body;
  if (!email || !email.includes('@')) {
    return res.json({ ok: false, error: '请输入有效邮箱' });
  }
  const normalized = email.trim().toLowerCase();
  const h = hashEmail(normalized);
  const existing = codes.get(h);
  if (existing && Date.now() - existing.ts < CODE_COOLDOWN_MS) {
    const wait = Math.ceil((CODE_COOLDOWN_MS - (Date.now() - existing.ts)) / 1000);
    return res.json({ ok: false, error: `请 ${wait} 秒后再试` });
  }
  const code = generateCode();
  codes.set(h, { code, ts: Date.now(), attempts: 0, email: normalized });
  try {
    await getTransporter().sendMail({
      from: `"光湖协作中心" <${SMTP_USER}>`,
      to: normalized,
      subject: '光湖 · 邮箱验证码',
      html: `<div style="font-family:sans-serif;max-width:480px;margin:0 auto;padding:32px;background:#0f172a;color:#e2e8f0;border-radius:12px">
        <h2 style="margin:0 0 16px;color:#60a5fa">光湖 · 语言世界</h2>
        <p style="margin:0 0 24px">您的注册验证码：</p>
        <div style="font-size:32px;letter-spacing:8px;text-align:center;padding:16px;background:rgba(96,165,250,0.1);border-radius:8px;font-family:monospace;color:#22d3ee">${code}</div>
        <p style="margin:24px 0 0;opacity:0.6;font-size:13px">5分钟内有效。若非本人操作请忽略。</p>
      </div>`
    });
    console.log(`[Register] Code sent to ${normalized.slice(0,3)}***`);
    res.json({ ok: true, message: '验证码已发送，请查收邮箱' });
  } catch (err) {
    codes.delete(h);
    console.error(`[Register] Send failed: ${err.message}`);
    res.json({ ok: false, error: '验证码发送失败，请稍后重试' });
  }
});

app.post('/verify', async (req, res) => {
  const { email, code, password } = req.body;
  if (!email || !code || !password) {
    return res.json({ ok: false, error: '邮箱、验证码和密码不能为空' });
  }
  if (password.length < 6) {
    return res.json({ ok: false, error: '密码至少6位' });
  }
  const normalized = email.trim().toLowerCase();
  const h = hashEmail(normalized);
  const pending = codes.get(h);
  if (!pending) return res.json({ ok: false, error: '验证码不存在或已过期，请重新获取' });
  if (Date.now() - pending.ts > CODE_EXPIRE_MS) {
    codes.delete(h);
    return res.json({ ok: false, error: '验证码已过期' });
  }
  if (pending.attempts >= 3) {
    codes.delete(h);
    return res.json({ ok: false, error: '错误次数过多，请重新获取' });
  }
  if (String(code).trim() !== pending.code) {
    pending.attempts++;
    return res.json({ ok: false, error: `验证码错误（${3 - pending.attempts} 次机会）` });
  }
  codes.delete(h);
  try {
    const pwHash = bcrypt.hashSync(password, 10);
    const userId = crypto.randomUUID();
    const username = normalized.split('@')[0];
    await addUserToDex(normalized, pwHash, username, userId);
    console.log(`[Register] User created: ${normalized.slice(0,3)}***`);
    res.json({ ok: true, message: '注册成功！请返回登录', loginUrl: '/outline/' });
  } catch (err) {
    console.error(`[Register] DB error: ${err.message}`);
    if (err.message === 'EMAIL_EXISTS') {
      return res.json({ ok: false, error: '该邮箱已注册，请直接登录' });
    }
    res.json({ ok: false, error: '注册失败，请稍后重试' });
  }
});

app.get('/health', (req, res) => {
  res.json({ ok: true, service: 'guanghu-register', db: 'python' });
});

app.listen(PORT, '127.0.0.1', () => {
  console.log(`[Register] Listening on 127.0.0.1:${PORT} (WAL mode)`);
});
