const jwt = require('jsonwebtoken');
const { User } = require('../models');
const { ApiError } = require('../utils/ApiError');
const { logger } = require('../utils/logger');
const { sequelize } = require('../models');

const generateTokens = (user) => {
  const accessToken = jwt.sign(
    { id: user.id, email: user.email, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );

  const refreshToken = jwt.sign(
    { id: user.id },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: '7d' }
  );

  return { accessToken, refreshToken };
};

module.exports = {
  async register(req, res, next) {
    const transaction = await sequelize.transaction();
    try {
      const { email, password } = req.body;

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

      if (existingUser) {
        throw new ApiError(409, 'Email already registered');
      }

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

      const tokens = generateTokens(user);
      await transaction.commit();

      logger.info(`New user registered: ${user.id}`);

      res.status(201).json({
        user: { id: user.id, email: user.email, role: user.role },
        ...tokens
      });
    } catch (error) {
      await transaction.rollback();
      logger.error('Registration error:', error);
      next(error);
    }
  },

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

      const user = await User.findOne({
        where: { email },
        attributes: ['id', 'email', 'password', 'role']
      });

      if (!user || !(await user.validatePassword(password))) {
        throw new ApiError(401, 'Invalid credentials');
      }

      const tokens = generateTokens(user);
      logger.info(`User logged in: ${user.id}`);

      res.json({
        user: { id: user.id, email: user.email, role: user.role },
        ...tokens
      });
    } catch (error) {
      logger.error('Login error:', error);
      next(error);
    }
  }
};