const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { body, validationResult } = require('express-validator');
const { getDb, returnToPool } = require('../database/init');
const { authenticateToken, requireAdmin, validateUserExists } = require('../middleware/auth');

const router = express.Router();

// Validation rules
const registerValidation = [
  body('email').isEmail().normalizeEmail().withMessage('Valid email is required'),
  body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters')
];

const adminRegisterValidation = [
  body('name').trim().isLength({ min: 2 }).withMessage('Name must be at least 2 characters'),
  body('email').isEmail().normalizeEmail().withMessage('Valid email is required'),
  body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters'),
  body('phone').optional().trim().isLength({ min: 10 }).withMessage('Valid phone number required')
];

const loginValidation = [
  body('email').trim().notEmpty().withMessage('Username/Email is required'),
  body('password').notEmpty().withMessage('Password is required')
];

// JWT generator
const generateToken = (user) => {
  return jwt.sign(
    {
      id: user.id,
      email: user.email,
      role: user.role
    },
    process.env.JWT_SECRET,
    { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
  );
};

// Register user
router.post('/register', registerValidation, async (req, res) => {
  let connection;
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });

    const { email, password } = req.body;
    connection = await getDb();

    const [rows] = await connection.query('SELECT id FROM users WHERE email = ?', [email]);
    if (rows.length > 0) {
      returnToPool(connection);
      return res.status(409).json({ error: 'Email already registered' });
    }

    const saltRounds = parseInt(process.env.BCRYPT_ROUNDS) || 12;
    const hashedPassword = await bcrypt.hash(password, saltRounds);
    const name = email.split('@')[0];

    const [result] = await connection.query(
      'INSERT INTO users (name, email, password, phone, role, status) VALUES (?, ?, ?, ?, ?, ?)',
      [name, email, hashedPassword, '', 'client', 'active']
    );

    const [userRows] = await connection.query(
      'SELECT id, name, email, phone, role, status, created_at FROM users WHERE id = ?',
      [result.insertId]
    );

    returnToPool(connection);
    const token = generateToken(userRows[0]);

    res.status(201).json({
      message: 'User registered successfully',
      token,
      user: userRows[0]
    });
  } catch (error) {
    console.error('Registration error:', error);
    if (connection) returnToPool(connection);
    res.status(500).json({ error: 'Server error during registration' });
  }
});

// Admin register
router.post('/admin/register', authenticateToken, requireAdmin, adminRegisterValidation, async (req, res) => {
  let connection;
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });

    const { name, email, password, phone, role = 'client' } = req.body;
    connection = await getDb();

    const [rows] = await connection.query('SELECT id FROM users WHERE email = ?', [email]);
    if (rows.length > 0) {
      returnToPool(connection);
      return res.status(409).json({ error: 'Email already registered' });
    }

    const saltRounds = parseInt(process.env.BCRYPT_ROUNDS) || 12;
    const hashedPassword = await bcrypt.hash(password, saltRounds);
    const validRole = ['admin', 'client'].includes(role) ? role : 'client';

    const [result] = await connection.query(
      'INSERT INTO users (name, email, password, phone, role, status) VALUES (?, ?, ?, ?, ?, ?)',
      [name, email, hashedPassword, phone || '', validRole, 'active']
    );

    const [userRows] = await connection.query(
      'SELECT id, name, email, role, phone, status, created_at FROM users WHERE id = ?',
      [result.insertId]
    );

    returnToPool(connection);
    res.status(201).json({
      message: 'User created successfully',
      user: userRows[0]
    });
  } catch (error) {
    console.error('Admin registration error:', error);
    if (connection) returnToPool(connection);
    res.status(500).json({ error: 'Server error during user creation' });
  }
});

// Login
router.post('/login', loginValidation, async (req, res) => {
  let connection;
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });

    const { email, password } = req.body;
    connection = await getDb();

    const [rows] = await connection.query(
      'SELECT id, name, email, password, role, status, avatar, created_at FROM users WHERE email = ?',
      [email]
    );

    returnToPool(connection);

    if (rows.length === 0) {
      return res.status(401).json({ error: 'Invalid email or password' });
    }

    const user = rows[0];

    if (user.status !== 'active') {
      return res.status(401).json({ error: 'Account is inactive. Please contact administrator.' });
    }

    const isValidPassword = await bcrypt.compare(password, user.password);
    if (!isValidPassword) {
      return res.status(401).json({ error: 'Invalid email or password' });
    }

    const { password: _, ...userWithoutPassword } = user;
    const token = generateToken(user);

    res.json({
      message: 'Login successful',
      token,
      user: userWithoutPassword
    });
  } catch (error) {
    console.error('Login error:', error);
    if (connection) returnToPool(connection);
    res.status(500).json({ error: 'Server error during login' });
  }
});

// Current user
router.get('/me', authenticateToken, validateUserExists, (req, res) => {
  res.json({
    user: req.userDetails
  });
});

// Refresh token
router.post('/refresh', authenticateToken, validateUserExists, (req, res) => {
  const newToken = generateToken(req.userDetails);
  res.json({
    message: 'Token refreshed successfully',
    token: newToken,
    user: req.userDetails
  });
});

// Logout
router.post('/logout', authenticateToken, (req, res) => {
  res.json({ message: 'Logout successful' });
});

module.exports = router;
