import Participant from '../models/Participant.js';
import DiaryDates from '../models/DiaryDates.js';
import DiaryMemberActivity from '../models/DiaryMemberActivity.js';
import { devLog } from '../utils/logger.js';
import { emitParticipantAdded, emitParticipantRemoved, emitParticipantUpdated } from '../services/socketService.js';

const PARTICIPANT_ATTRIBUTES = ['id', 'diaryDateId', 'memberId', 'attendanceStatus', 'groupId', 'notes', 'createdAt', 'updatedAt'];

export const getParticipants = async (req, res) => {
    try {
        const { dateId } = req.params;
        const participants = await Participant.findAll({ 
            where: { diaryDateId: dateId },
            attributes: PARTICIPANT_ATTRIBUTES
        });
        res.status(200).json(participants);
    } catch (error) {
        devLog(error);
        res.status(500).json({ error: 'Fehler beim Abrufen der Teilnehmer' });
    }
};

export const updateParticipantGroup = async (req, res) => {
    try {
        const { dateId, memberId } = req.params;
        const { groupId } = req.body;
        
        const participant = await Participant.findOne({
            where: { 
                diaryDateId: dateId,
                memberId: memberId
            },
            include: [{
                model: DiaryDates,
                as: 'diaryDate',
                attributes: ['clubId']
            }]
        });
        
        if (!participant) {
            return res.status(404).json({ error: 'Teilnehmer nicht gefunden' });
        }
        
        participant.groupId = groupId || null;
        await participant.save();
        
        // Lade den Participant erneut aus der DB, um sicherzustellen, dass wir den aktuellen Wert haben
        const updatedParticipant = await Participant.findOne({
            where: { 
                diaryDateId: dateId,
                memberId: memberId
            },
            include: [{
                model: DiaryDates,
                as: 'diaryDate',
                attributes: ['clubId']
            }]
        });
        
        // Emit Socket-Event mit dem aktualisierten Participant
        if (updatedParticipant?.diaryDate?.clubId) {
            emitParticipantUpdated(updatedParticipant.diaryDate.clubId, dateId, updatedParticipant);
        }
        
        res.status(200).json(updatedParticipant || participant);
    } catch (error) {
        devLog(error);
        res.status(500).json({ error: 'Fehler beim Aktualisieren der Teilnehmer-Gruppenzuordnung' });
    }
};

export const addParticipant = async (req, res) => {
    try {
        const { diaryDateId, memberId } = req.body;
        const [participant, created] = await Participant.findOrCreate({
            where: { diaryDateId, memberId },
            defaults: { diaryDateId, memberId, attendanceStatus: 'present' }
        });

        participant.attendanceStatus = 'present';
        await participant.save();
        
        // Hole DiaryDate für clubId
        const diaryDate = await DiaryDates.findByPk(diaryDateId);
        if (diaryDate?.clubId) {
            if (created) {
                emitParticipantAdded(diaryDate.clubId, diaryDateId, participant);
            } else {
                emitParticipantUpdated(diaryDate.clubId, diaryDateId, participant);
            }
        }
        
        res.status(201).json(participant);
    } catch (error) {
        devLog(error);
        res.status(500).json({ error: 'Fehler beim Hinzufügen des Teilnehmers' });
    }
};

export const removeParticipant = async (req, res) => {
    try {
        const { diaryDateId, memberId } = req.body;
        
        // Hole DiaryDate für clubId vor dem Löschen
        const diaryDate = await DiaryDates.findByPk(diaryDateId);
        const clubId = diaryDate?.clubId;

        const participant = await Participant.findOne({
            where: { diaryDateId, memberId },
            attributes: ['id']
        });

        if (participant) {
            await DiaryMemberActivity.destroy({ where: { participantId: participant.id } });
        }
        
        await Participant.destroy({ where: { diaryDateId, memberId } });
        
        // Emit Socket-Event
        if (clubId) {
            emitParticipantRemoved(clubId, diaryDateId, memberId);
        }
        
        res.status(200).json({ message: 'Teilnehmer entfernt' });
    } catch (error) {
        devLog(error);
        res.status(500).json({ error: 'Fehler beim Entfernen des Teilnehmers' });
    }
};

export const updateParticipantStatus = async (req, res) => {
    try {
        const { dateId, memberId } = req.params;
        const { attendanceStatus } = req.body;

        if (!['excused', 'cancelled'].includes(attendanceStatus)) {
            return res.status(400).json({ error: 'Ungültiger Teilnehmerstatus' });
        }

        const diaryDate = await DiaryDates.findByPk(dateId);
        if (!diaryDate) {
            return res.status(404).json({ error: 'Trainingstag nicht gefunden' });
        }

        const [participant] = await Participant.findOrCreate({
            where: {
                diaryDateId: dateId,
                memberId
            },
            defaults: {
                diaryDateId: dateId,
                memberId,
                attendanceStatus
            }
        });

        participant.attendanceStatus = attendanceStatus;
        participant.groupId = null;
        await participant.save();
        await DiaryMemberActivity.destroy({ where: { participantId: participant.id } });

        const updatedParticipant = await Participant.findOne({
            where: {
                diaryDateId: dateId,
                memberId
            },
            attributes: PARTICIPANT_ATTRIBUTES
        });

        if (diaryDate.clubId && updatedParticipant) {
            emitParticipantUpdated(diaryDate.clubId, dateId, updatedParticipant);
        }

        res.status(200).json(updatedParticipant || participant);
    } catch (error) {
        devLog(error);
        res.status(500).json({ error: 'Fehler beim Aktualisieren des Teilnehmerstatus' });
    }
};
