import DiaryDate from '../models/DiaryDates.js';
import Club from '../models/Club.js';
import DiaryNote from '../models/DiaryNote.js';
import { DiaryTag } from '../models/DiaryTag.js';
import DiaryDateTag from '../models/DiaryDateTag.js';
import { checkAccess } from '../utils/userUtils.js';
import HttpError from '../exceptions/HttpError.js';

class DiaryService {
    async getDatesForClub(userToken, clubId) {
        console.log('[DiaryService::getDatesForClub] - Check user access');
        await checkAccess(userToken, clubId);
        console.log('[DiaryService::getDatesForClub] - Validate club existence');
        const club = await Club.findByPk(clubId);
        if (!club) {
            throw new HttpError('Club not found', 404);
        }
        console.log('[DiaryService::getDatesForClub] - Load diary dates');
        const dates = await DiaryDate.findAll({
            where: { clubId },
            include: [
                { model: DiaryNote, as: 'diaryNotes' },  // Der Alias für DiaryNote ist korrekt
                { model: DiaryTag, as: 'diaryTags' },    // Hier muss der Alias auf 'diaryTags' geändert werden
            ],
            order: [['date', 'DESC'], ['trainingStart', 'ASC']]
        });
        return dates;
    }

    async createDateForClub(userToken, clubId, date, trainingStart, trainingEnd) {
        console.log('[DiaryService::createDateForClub] - Check user access');
        await checkAccess(userToken, clubId);
        console.log('[DiaryService::createDateForClub] - Validate club existence');
        const club = await Club.findByPk(clubId);
        if (!club) {
            throw new HttpError('Club not found', 404);
        }
        console.log('[DiaryService::createDateForClub] - Validate date');
        const parsedDate = new Date(date);
        if (isNaN(parsedDate.getTime())) {
            throw new HttpError('Invalid date format', 400);
        }
        if (trainingStart && trainingEnd && trainingStart >= trainingEnd) {
            throw new HttpError('Training start time must be before training end time', 400);
        }
        console.log('[DiaryService::createDateForClub] - Create new diary date');
        const newDate = await DiaryDate.create({
            date: parsedDate,
            clubId,
            trainingStart: trainingStart || null,
            trainingEnd: trainingEnd || null,
        });

        return newDate;
    }

    async updateTrainingTimes(userToken, clubId, dateId, trainingStart, trainingEnd) {
        console.log('[DiaryService::updateTrainingTimes] - Check user access');
        await checkAccess(userToken, clubId);
        console.log('[DiaryService::updateTrainingTimes] - Validate date');
        const diaryDate = await DiaryDate.findOne({ where: { clubId, id: dateId } });
        if (!diaryDate) {
            throw new HttpError('Diary entry not found', 404);
        }
        if (trainingStart && trainingEnd && trainingStart >= trainingEnd) {
            throw new HttpError('Training start time must be before training end time', 400);
        }
        console.log('[DiaryService::updateTrainingTimes] - Update training times');
        diaryDate.trainingStart = trainingStart || null;
        diaryDate.trainingEnd = trainingEnd || null;
        await diaryDate.save();
        return diaryDate;
    }

    async addNoteToDate(userToken, diaryDateId, content) {
        console.log('[DiaryService::addNoteToDate] - Add note');
        await checkAccess(userToken, diaryDateId);
        await DiaryNote.create({ diaryDateId, content });
        return await DiaryNote.findAll({ where: { diaryDateId }, order: [['createdAt', 'DESC']] });
    }

    async deleteNoteFromDate(userToken, noteId) {
        console.log('[DiaryService::deleteNoteFromDate] - Delete note');
        const note = await DiaryNote.findByPk(noteId);
        if (!note) {
            throw new HttpError('Note not found', 404);
        }
        await checkAccess(userToken, note.diaryDateId);
        await note.destroy();
        return await DiaryNote.findAll({ where: { diaryDateId: note.diaryDateId }, order: [['createdAt', 'DESC']] });
    }

    async addTagToDate(userToken, diaryDateId, tagName) {
        console.log('[DiaryService::addTagToDate] - Add tag');
        await checkAccess(userToken, diaryDateId);
        let tag = await DiaryTag.findOne({ where: { name: tagName } });
        if (!tag) {
            tag = await DiaryTag.create({ name: tagName });
        }
        const diaryDate = await DiaryDate.findByPk(diaryDateId);
        await diaryDate.addTag(tag);
        return await diaryDate.getTags();
    }

    async addTagToDiaryDate(userToken, clubId, diaryDateId, tagId) {
        checkAccess(userToken, clubId);
        console.log(`[DiaryService::addTagToDiaryDate] - diaryDateId: ${diaryDateId}, tagId: ${tagId}`);
        const diaryDate = await DiaryDate.findByPk(diaryDateId);
        if (!diaryDate) {
            throw new HttpError('DiaryDate not found', 404);
        }
        console.log('[DiaryService::addTagToDiaryDate] - Add tag to diary date');
        const existingEntry = await DiaryDateTag.findOne({
            where: { diaryDateId, tagId }
        });
        if (existingEntry) {
            return;
        }
        console.log('[DiaryService::addTagToDiaryDate] - Tag not found, creating new entry');
        const tag = await DiaryTag.findByPk(tagId);  
        if (!tag) {
            throw new HttpError('Tag not found', 404);
        }
        console.log('[DiaryService::addTagToDiaryDate] - Add tag to diary date');
        await DiaryDateTag.create({
            diaryDateId,
            tagId
        });
        console.log('[DiaryService::addTagToDiaryDate] - Get tags');
        const tags = await DiaryDateTag.findAll({ where: {
            diaryDateId: diaryDateId },
            include: {
                model: DiaryTag,
                as: 'tag'
            }
        });  
        console.log(tags);
        return tags.map(tag => tag.tag);
    }

    async getDiaryNotesForDateAndMember(diaryDateId, memberId) {
        console.log('[DiaryService::getDiaryNotesForDateAndMember] - Fetching notes');
        return await DiaryNote.findAll({
            where: { diaryDateId, memberId },
            order: [['createdAt', 'DESC']]
        });
    }

    async removeTagFromDiaryDate(userToken, clubId, tagId) {
        await checkAccess(userToken, clubId);
        await DiaryDateTag.destroy({ where: { tagId } });
    }

}

export default new DiaryService();
