const database = require('../config/database');
const { Op } = require('sequelize');

/**
 * Repository für User-Datenbankzugriff
 * Verwendet Sequelize ORM
 */
class UserRepository {
  /**
   * Alle Benutzer abrufen
   * @returns {Promise<Array>} Liste aller Benutzer
   */
  async findAll() {
    const { User, State } = database.getModels();
    
    return await User.findAll({
      include: [{
        model: State,
        as: 'state',
        required: false
      }],
      order: [['full_name', 'ASC']]
    });
  }

  /**
   * Benutzer anhand der ID abrufen
   * @param {number} id - Benutzer-ID
   * @returns {Promise<Object|null>} Benutzer oder null
   */
  async findById(id) {
    const { User, State } = database.getModels();
    
    return await User.findByPk(id, {
      include: [{
        model: State,
        as: 'state',
        required: false
      }]
    });
  }

  /**
   * Benutzer anhand der E-Mail abrufen
   * @param {string} email - E-Mail-Adresse
   * @returns {Promise<Object|null>} Benutzer oder null
   */
  async findByEmail(email) {
    const { User, AuthInfo } = database.getModels();
    
    return await User.findOne({
      include: [{
        model: AuthInfo,
        as: 'authInfo',
        where: { email },
        required: true
      }]
    });
  }

  /**
   * Wochenarbeitszeit für Benutzer abrufen
   * @param {number} userId - Benutzer-ID
   * @param {Date} date - Datum (optional, Standard: heute)
   * @returns {Promise<Object|null>} Wochenarbeitszeit-Einstellung
   */
  async getWeeklyWorktime(userId, date = new Date()) {
    const { WeeklyWorktime } = database.getModels();
    
    const dateStr = date.toISOString().split('T')[0];
    
    return await WeeklyWorktime.findOne({
      where: {
        user_id: userId,
        [Op.or]: [
          { starting_from: null },
          { starting_from: { [Op.lte]: dateStr } }
        ],
        [Op.or]: [
          { ends_at: null },
          { ends_at: { [Op.gte]: dateStr } }
        ]
      },
      order: [['starting_from', 'DESC']]
    });
  }

  /**
   * Benutzer erstellen
   * @param {Object} userData - Benutzerdaten
   * @returns {Promise<Object>} Erstellter Benutzer
   */
  async create(userData) {
    const { User } = database.getModels();
    
    const {
      full_name,
      role = 0,
      daily_hours = 8,
      week_hours = 40,
      week_workdays = 5,
      state_id = null,
      preferred_title_type = 0
    } = userData;

    return await User.create({
      version: 0,
      full_name,
      role,
      daily_hours,
      week_hours,
      week_workdays,
      state_id,
      preferred_title_type,
      last_change: new Date()
    });
  }

  /**
   * Benutzer aktualisieren
   * @param {number} id - Benutzer-ID
   * @param {Object} updateData - Zu aktualisierende Daten
   * @returns {Promise<Object>} Aktualisierter Benutzer
   */
  async update(id, updateData) {
    const { User } = database.getModels();
    
    const user = await User.findByPk(id);
    if (!user) {
      throw new Error(`Benutzer mit ID ${id} nicht gefunden`);
    }

    const allowedFields = [
      'full_name', 'role', 'daily_hours', 'week_hours', 
      'week_workdays', 'state_id', 'preferred_title_type'
    ];

    const updates = {};
    allowedFields.forEach(field => {
      if (updateData[field] !== undefined) {
        updates[field] = updateData[field];
      }
    });

    if (Object.keys(updates).length > 0) {
      updates.version = user.version + 1;
      updates.last_change = new Date();
      
      await user.update(updates);
    }

    return user;
  }

  /**
   * Benutzer mit allen Beziehungen abrufen
   * @param {number} id - Benutzer-ID
   * @returns {Promise<Object|null>} Benutzer mit Beziehungen
   */
  async findByIdWithRelations(id) {
    const { User, State, AuthInfo, WeeklyWorktime, Vacation, Sick } = database.getModels();
    
    return await User.findByPk(id, {
      include: [
        {
          model: State,
          as: 'state',
          required: false
        },
        {
          model: AuthInfo,
          as: 'authInfo',
          required: false
        },
        {
          model: WeeklyWorktime,
          as: 'weeklyWorktimes',
          required: false
        },
        {
          model: Vacation,
          as: 'vacations',
          required: false
        },
        {
          model: Sick,
          as: 'sickLeaves',
          required: false
        }
      ]
    });
  }
}

module.exports = new UserRepository();
