import { checkAccess } from '../utils/userUtils.js';
import TrainingTime from '../models/TrainingTime.js';
import TrainingGroup from '../models/TrainingGroup.js';
import HttpError from '../exceptions/HttpError.js';

class TrainingTimeService {
    async getTrainingTimes(userToken, clubId) {
        await checkAccess(userToken, clubId);
        
        const groups = await TrainingGroup.findAll({
            where: { clubId },
            include: [{
                model: TrainingTime,
                as: 'trainingTimes',
                required: false,
                separate: true,
                order: [['weekday', 'ASC'], ['sortOrder', 'ASC'], ['startTime', 'ASC']]
            }],
            order: [['isPreset', 'DESC'], ['sortOrder', 'ASC'], ['name', 'ASC']]
        });
        
        return groups.map(group => {
            const groupData = group.toJSON ? group.toJSON() : group;
            return {
                ...groupData,
                trainingTimes: Array.isArray(groupData.trainingTimes) 
                    ? groupData.trainingTimes.sort((a, b) => {
                        if (a.weekday !== b.weekday) return a.weekday - b.weekday;
                        if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder;
                        return a.startTime.localeCompare(b.startTime);
                    })
                    : []
            };
        });
    }
    
    async createTrainingTime(userToken, clubId, trainingGroupId, weekday, startTime, endTime) {
        await checkAccess(userToken, clubId);
        
        // Validate that the training group belongs to the club
        const group = await TrainingGroup.findOne({
            where: { id: trainingGroupId, clubId }
        });
        
        if (!group) {
            throw new HttpError('Trainingsgruppe nicht gefunden', 404);
        }
        
        // Validate weekday (0-6)
        if (weekday < 0 || weekday > 6) {
            throw new HttpError('Ungültiger Wochentag (0-6)', 400);
        }
        
        // Validate times
        if (!startTime || !endTime) {
            throw new HttpError('Start- und Endzeit müssen angegeben werden', 400);
        }
        
        if (startTime >= endTime) {
            throw new HttpError('Startzeit muss vor Endzeit liegen', 400);
        }
        
        // Get max sortOrder for this weekday and group
        const maxSortOrder = await TrainingTime.max('sortOrder', {
            where: {
                trainingGroupId,
                weekday
            }
        }) || 0;
        
        const trainingTime = await TrainingTime.create({
            trainingGroupId,
            weekday,
            startTime,
            endTime,
            sortOrder: maxSortOrder + 1
        });
        
        return trainingTime;
    }
    
    async updateTrainingTime(userToken, clubId, timeId, weekday, startTime, endTime) {
        await checkAccess(userToken, clubId);
        
        const trainingTime = await TrainingTime.findByPk(timeId, {
            include: [{
                model: TrainingGroup,
                as: 'trainingGroup'
            }]
        });
        
        if (!trainingTime || !trainingTime.trainingGroup) {
            throw new HttpError('Trainingszeit nicht gefunden', 404);
        }
        
        if (trainingTime.trainingGroup.clubId !== parseInt(clubId)) {
            throw new HttpError('Keine Berechtigung', 403);
        }
        
        // Validate weekday (0-6)
        if (weekday !== undefined && (weekday < 0 || weekday > 6)) {
            throw new HttpError('Ungültiger Wochentag (0-6)', 400);
        }
        
        // Validate times
        if (startTime && endTime && startTime >= endTime) {
            throw new HttpError('Startzeit muss vor Endzeit liegen', 400);
        }
        
        if (weekday !== undefined) trainingTime.weekday = weekday;
        if (startTime !== undefined) trainingTime.startTime = startTime;
        if (endTime !== undefined) trainingTime.endTime = endTime;
        
        await trainingTime.save();
        return trainingTime;
    }
    
    async deleteTrainingTime(userToken, clubId, timeId) {
        await checkAccess(userToken, clubId);
        
        const trainingTime = await TrainingTime.findByPk(timeId, {
            include: [{
                model: TrainingGroup,
                as: 'trainingGroup'
            }]
        });
        
        if (!trainingTime || !trainingTime.trainingGroup) {
            throw new HttpError('Trainingszeit nicht gefunden', 404);
        }
        
        if (trainingTime.trainingGroup.clubId !== parseInt(clubId)) {
            throw new HttpError('Keine Berechtigung', 403);
        }
        
        await trainingTime.destroy();
        return { success: true };
    }
}

export default new TrainingTimeService();

