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

/**
 * Service-Klasse für Feiertage
 * Verwaltet bundesweite und regionale Feiertage
 */
class HolidayService {
  /**
   * Holt alle verfügbaren Bundesländer
   * @returns {Promise<Array>} Array von States
   */
  async getAllStates() {
    const { State } = database.getModels();
    
    const states = await State.findAll({
      order: [['state_name', 'ASC']],
      raw: true
    });
    
    return states.map(s => ({
      id: s.id,
      name: s.state_name
    }));
  }

  /**
   * Holt alle Feiertage, aufgeteilt in zukünftige und vergangene
   * Vergangene: Nur aktuelles Jahr und maximal 3 Monate zurück
   * @returns {Promise<Object>} { future: [], past: [] }
   */
  async getAllHolidays() {
    const { Holiday, State, HolidayState } = database.getModels();
    
    const today = new Date();
    const currentYear = today.getFullYear();
    const todayStr = `${currentYear}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
    
    // Berechne Startdatum für vergangene Feiertage
    const threeMonthsAgo = new Date(today);
    threeMonthsAgo.setMonth(today.getMonth() - 3);
    const yearStart = new Date(currentYear, 0, 1);
    const pastStartDate = yearStart < threeMonthsAgo ? yearStart : threeMonthsAgo;
    const pastStartDateStr = `${pastStartDate.getFullYear()}-${String(pastStartDate.getMonth() + 1).padStart(2, '0')}-${String(pastStartDate.getDate()).padStart(2, '0')}`;
    
    // Zukünftige Feiertage (inkl. heute) mit States
    const futureHolidays = await Holiday.findAll({
      where: {
        date: {
          [Op.gte]: todayStr
        }
      },
      include: [
        {
          model: State,
          as: 'states',
          attributes: ['id', 'state_name'],
          through: { attributes: [] } // Keine Attribute der Junction Table
        }
      ],
      order: [['date', 'ASC']]
    });
    
    // Vergangene Feiertage (nur aktuelles Jahr / letzte 3 Monate) mit States
    const pastHolidays = await Holiday.findAll({
      where: {
        date: {
          [Op.gte]: pastStartDateStr,
          [Op.lt]: todayStr
        }
      },
      include: [
        {
          model: State,
          as: 'states',
          attributes: ['id', 'state_name'],
          through: { attributes: [] }
        }
      ],
      order: [['date', 'DESC']]
    });
    
    return {
      future: futureHolidays.map(h => this._formatHoliday(h)),
      past: pastHolidays.map(h => this._formatHoliday(h))
    };
  }

  /**
   * Erstellt einen neuen Feiertag
   * @param {string} date - Datum (YYYY-MM-DD)
   * @param {number} hours - Freie Stunden (Standard: 8)
   * @param {string} description - Beschreibung
   * @param {Array<number>} stateIds - Array von State-IDs (leer = bundesweit)
   * @returns {Promise<Object>} Erstellter Feiertag
   */
  async createHoliday(date, hours, description, stateIds = []) {
    const { Holiday, State, HolidayState } = database.getModels();
    
    // Prüfe ob schon ein Feiertag an diesem Datum existiert
    const existing = await Holiday.findOne({
      where: { date }
    });
    
    if (existing) {
      throw new Error('An diesem Datum existiert bereits ein Feiertag');
    }
    
    const holiday = await Holiday.create({
      date,
      hours: hours || 8,
      description,
      version: 0
    });
    
    // Verknüpfe mit States (falls angegeben)
    if (stateIds && stateIds.length > 0) {
      for (const stateId of stateIds) {
        await HolidayState.create({
          holiday_id: holiday.id,
          state_id: stateId
        });
      }
    }
    
    // Lade Holiday mit States neu
    const holidayWithStates = await Holiday.findByPk(holiday.id, {
      include: [
        {
          model: State,
          as: 'states',
          attributes: ['id', 'state_name'],
          through: { attributes: [] }
        }
      ]
    });
    
    return this._formatHoliday(holidayWithStates);
  }

  /**
   * Löscht einen Feiertag
   * @param {number} id - Holiday-ID
   * @returns {Promise<void>}
   */
  async deleteHoliday(id) {
    const { Holiday } = database.getModels();
    
    const holiday = await Holiday.findByPk(id);
    
    if (!holiday) {
      throw new Error('Feiertag nicht gefunden');
    }
    
    await holiday.destroy();
  }

  /**
   * Formatiert einen Feiertag für die API
   */
  _formatHoliday(holiday) {
    // Holiday kann ein Plain Object (raw: true) oder eine Sequelize Instance sein
    const states = holiday.states || [];
    const stateNames = Array.isArray(states) 
      ? states.map(s => s.state_name || s.name).filter(Boolean)
      : [];
    
    return {
      id: holiday.id,
      date: holiday.date,
      hours: holiday.hours,
      description: holiday.description,
      states: stateNames,
      isFederal: stateNames.length === 0 // Kein State = Bundesfeiertag
    };
  }
}

module.exports = new HolidayService();

