const User = require('../models/User');
const jwt = require('jsonwebtoken');
const logger = require('../config/logger');
const { ValidationError } = require('sequelize');
const { rateLimiter } = require('../middleware/auth');
const crypto = require('crypto');

const generateToken = (id) => {
  return jwt.sign({ id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRES_IN || '1d',
    algorithm: 'HS256'
  });
};

const signup = async (req, res, next) => {
  const transaction = await sequelize.transaction();
  try {
    const { email, password, name } = req.body;

    const userExists = await User.findOne({
      where: { email },
      transaction
    });

    if (userExists) {
      await transaction.rollback();
      return res.status(409).json({
        status: 'error',
        message: 'Email already registered'
      });
    }

    const user = await User.create(
      { email, password, name },
      { transaction }
    );

    const token = generateToken(user.id);
    
    await transaction.commit();
    logger.info(`New user registered: ${user.id}`);

    res.status(201).json({
      status: 'success',
      data: {
        token,
        user: {
          id: user.id,
          email: user.email,
          name: user.name,
          role: user.role
        }
      }
    });
  } catch (error) {
    await transaction.rollback();
    logger.error('Signup error:', { error: error.message, stack: error.stack });
    next(error);
  }
};

const login = async (req, res, next) => {
  try {
    const { email, password } = req.body;

    const user = await User.findOne({ where: { email } });
    if (!user || !(await user.comparePassword(password))) {
      if (user) {
        await user.increment('failedLoginAttempts');
        await rateLimiter(req, user);
      }
      return res.status(401).json({
        status: 'error',
        message: 'Invalid credentials'
      });
    }

    if (user.lockUntil && user.lockUntil > Date.now()) {
      return res.status(423).json({
        status: 'error',
        message: 'Account is locked. Try again later'
      });
    }

    await user.update({
      lastLogin: new Date(),
      failedLoginAttempts: 0,
      lockUntil: null
    });

    const token = generateToken(user.id);

    res.json({
      status: 'success',
      data: {
        token,
        user: {
          id: user.id,
          email: user.email,
          name: user.name,
          role: user.role
        }
      }
    });
  } catch (error) {
    logger.error('Login error:', { error: error.message, stack: error.stack });
    next(error);
  }
};

module.exports = { signup, login };