const router  = require('express').Router();
const bcrypt  = require('bcryptjs');
const jwt     = require('jsonwebtoken');
const { body, validationResult } = require('express-validator');
const prisma  = require('../config/db');
const redis   = require('../config/redis');
const { requireAuth } = require('../middleware/auth');
const { writeAuditLog } = require('../middleware/audit');

function signToken(user) {
  return jwt.sign(
    { id: user.id, email: user.email, role: user.role, nickname: user.nickname },
    process.env.JWT_SECRET,
    { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
  );
}

// POST /api/auth/register
router.post('/register', [
  body('email').isEmail().normalizeEmail(),
  body('password').isLength({ min: 8 }),
  body('nickname').trim().isLength({ min: 2, max: 30 }),
], async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) return res.status(400).json({ error: errors.array()[0].msg });

  const { email, password, nickname } = req.body;
  try {
    const exists = await prisma.user.findFirst({
      where: { OR: [{ email }, { nickname }] },
    });
    if (exists) {
      const field = exists.email === email ? '이메일' : '닉네임';
      return res.status(409).json({ error: `이미 사용 중인 ${field}입니다` });
    }

    const passwordHash = await bcrypt.hash(password, 12);
    const user = await prisma.user.create({
      data: { email, passwordHash, nickname },
    });

    await writeAuditLog({ userId: user.id, action: 'REGISTER', req, responseStatus: 201 });
    const token = signToken(user);
    res.status(201).json({ token, user: { id: user.id, email: user.email, nickname: user.nickname, role: user.role } });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: '서버 오류' });
  }
});

// POST /api/auth/login
router.post('/login', [
  body('email').isEmail().normalizeEmail(),
  body('password').notEmpty(),
], async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) return res.status(400).json({ error: errors.array()[0].msg });

  const { email, password } = req.body;
  try {
    const user = await prisma.user.findUnique({ where: { email } });
    if (!user || !await bcrypt.compare(password, user.passwordHash)) {
      await writeAuditLog({ action: 'LOGIN_FAIL', req, metadata: { email }, responseStatus: 401 });
      return res.status(401).json({ error: '이메일 또는 비밀번호가 올바르지 않습니다' });
    }
    if (!user.isActive) return res.status(403).json({ error: '비활성화된 계정입니다' });

    await prisma.user.update({
      where: { id: user.id },
      data: { lastLoginAt: new Date(), lastLoginIp: req.ip },
    });

    await writeAuditLog({ userId: user.id, action: 'LOGIN', req, responseStatus: 200 });
    const token = signToken(user);
    res.json({ token, user: { id: user.id, email: user.email, nickname: user.nickname, role: user.role } });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: '서버 오류' });
  }
});

// POST /api/auth/logout
router.post('/logout', requireAuth, async (req, res) => {
  try {
    // 토큰 남은 TTL만큼 블랙리스트에 등록
    const decoded = jwt.decode(req.token);
    const ttl = decoded.exp - Math.floor(Date.now() / 1000);
    if (ttl > 0) await redis.set(`bl:${req.token}`, '1', 'EX', ttl);
    await writeAuditLog({ userId: req.user.id, action: 'LOGOUT', req, responseStatus: 200 });
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: '서버 오류' });
  }
});

// GET /api/auth/me
router.get('/me', requireAuth, async (req, res) => {
  try {
    const user = await prisma.user.findUnique({
      where: { id: req.user.id },
      select: { id: true, email: true, nickname: true, role: true, profileImageUrl: true, createdAt: true },
    });
    if (!user) return res.status(404).json({ error: '사용자를 찾을 수 없습니다' });
    res.json(user);
  } catch (err) {
    res.status(500).json({ error: '서버 오류' });
  }
});

// PUT /api/auth/me (프로필 업데이트)
router.put('/me', requireAuth, [
  body('nickname').optional().trim().isLength({ min: 2, max: 30 }),
], async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) return res.status(400).json({ error: errors.array()[0].msg });

  const { nickname } = req.body;
  try {
    if (nickname) {
      const dup = await prisma.user.findFirst({ where: { nickname, NOT: { id: req.user.id } } });
      if (dup) return res.status(409).json({ error: '이미 사용 중인 닉네임입니다' });
    }
    const updated = await prisma.user.update({
      where: { id: req.user.id },
      data: { ...(nickname && { nickname }) },
      select: { id: true, email: true, nickname: true, role: true },
    });
    res.json(updated);
  } catch (err) {
    res.status(500).json({ error: '서버 오류' });
  }
});

module.exports = router;
