import { UserRepository } from '../../infrastructure/repositories/UserRepository.js';
import { 
  hashPassword, 
  verifyPassword, 
  generateAccessToken, 
  generateRefreshToken,
  setAuthCookies,
  clearAuthCookies,
  validateRegisterInput,
  validateLoginInput,
  verifyRefreshToken,
  createSession,
  deleteSession
} from '../../infrastructure/auth/authUtils.js';

export class AuthController {
  constructor(userRepository) {
    this.userRepository = userRepository || new UserRepository();
  }

  /**
   * POST /api/auth/register
   * Új felhasználó regisztrációja
   */
  async register(req, res) {
    try {
      const { email, username, password } = req.body;

      // 1. Input validáció
      const validation = validateRegisterInput(req.body);
      if (!validation.isValid) {
        return res.status(400).json({
          success: false,
          errors: validation.errors
        });
      }

      // 2. Email uniqueness ellenőrzés
      const existingUserByEmail = await this.userRepository.findByEmail(email);
      if (existingUserByEmail) {
        return res.status(400).json({
          success: false,
          error: 'Email already in use'
        });
      }

      // 3. Username uniqueness ellenőrzés
      const existingUserByUsername = await this.userRepository.findByUsername(username);
      if (existingUserByUsername) {
        return res.status(400).json({
          success: false,
          error: 'Username already taken'
        });
      }

      // 4. Jelszó hash-elés
      const hashedPassword = await hashPassword(password);

      // 5. User létrehozása
      const user = await this.userRepository.create({
        email,
        username,
        password: hashedPassword,
        role: 'USER'
      });

      // 6. JWT tokenek generálása
      const accessToken = generateAccessToken(user);
      const refreshToken = generateRefreshToken(user);

      // 7. Cookie-k beállítása
      setAuthCookies(res, accessToken, refreshToken);

      // 8. Redis session (opcionális)
      await createSession(user.id, { email: user.email, username: user.username });

      // 9. Válasz (jelszó nélkül!)
      const { password: _, ...userWithoutPassword } = user;
      res.status(201).json({
        success: true,
        message: 'User registered successfully',
        data: {
          user: userWithoutPassword,
          accessToken,
          refreshToken
        }
      });
    } catch (error) {
      console.error('Register error:', error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * POST /api/auth/login
   * Bejelentkezés
   */
  async login(req, res) {
    try {
      const { email, username, password } = req.body;

      // 1. Input validáció
      const validation = validateLoginInput(req.body);
      if (!validation.isValid) {
        return res.status(400).json({
          success: false,
          errors: validation.errors
        });
      }

      // 2. User keresése (email VAGY username alapján)
      let user;
      if (email) {
        user = await this.userRepository.findByEmail(email);
      } else if (username) {
        user = await this.userRepository.findByUsername(username);
      }

      if (!user) {
        return res.status(401).json({
          success: false,
          error: 'Invalid credentials'
        });
      }

      // 3. Jelszó ellenőrzés
      const isPasswordValid = await verifyPassword(password, user.password);
      if (!isPasswordValid) {
        return res.status(401).json({
          success: false,
          error: 'Invalid credentials'
        });
      }

      // 4. JWT tokenek generálása
      const accessToken = generateAccessToken(user);
      const refreshToken = generateRefreshToken(user);

      // 5. Cookie-k beállítása
      setAuthCookies(res, accessToken, refreshToken);

      // 6. Redis session
      await createSession(user.id, { email: user.email, username: user.username });

      // 7. Válasz (jelszó nélkül!)
      const { password: _, ...userWithoutPassword } = user;
      res.json({
        success: true,
        message: 'Login successful',
        data: {
          user: userWithoutPassword,
          accessToken,
          refreshToken
        }
      });
    } catch (error) {
      console.error('Login error:', error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * POST /api/auth/logout
   * Kijelentkezés
   */
  async logout(req, res) {
    try {
      // 1. Cookie-k törlése
      clearAuthCookies(res);

      // 2. Redis session törlése
      if (req.user && req.user.id) {
        await deleteSession(req.user.id);
      }

      res.json({
        success: true,
        message: 'Logged out successfully'
      });
    } catch (error) {
      console.error('Logout error:', error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * POST /api/auth/refresh
   * Token frissítés
   */
  async refreshToken(req, res) {
    try {
      // 1. Refresh token kiolvasása
      const refreshToken = req.cookies.refreshToken;
      if (!refreshToken) {
        return res.status(401).json({
          success: false,
          error: 'Refresh token not found'
        });
      }

      // 2. Refresh token validálás
      const decoded = verifyRefreshToken(refreshToken);

      // 3. User lekérése
      const user = await this.userRepository.findById(decoded.userId);
      if (!user) {
        return res.status(401).json({
          success: false,
          error: 'User not found'
        });
      }

      // 4. Új access token generálás
      const newAccessToken = generateAccessToken(user);

      // 5. Cookie frissítése
      res.cookie('accessToken', newAccessToken, {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'strict',
        maxAge: 7 * 24 * 60 * 60 * 1000
      });

      res.json({
        success: true,
        data: {
          accessToken: newAccessToken
        }
      });
    } catch (error) {
      console.error('Refresh token error:', error);
      res.status(401).json({
        success: false,
        error: 'Invalid refresh token'
      });
    }
  }

  /**
   * GET /api/auth/me
   * Bejelentkezett user adatai
   */
  async getCurrentUser(req, res) {
    try {
      // req.user-t az authenticateToken middleware állította be
      const { password: _, ...userWithoutPassword } = req.user;
      
      res.json({
        success: true,
        data: {
          user: userWithoutPassword
        }
      });
    } catch (error) {
      console.error('Get current user error:', error);
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }
}
