import DiaryDateActivity from '../models/DiaryDateActivity.js';
import GroupActivity from '../models/GroupActivity.js';
import Group from '../models/Group.js';
import PredefinedActivity from '../models/PredefinedActivity.js';
import PredefinedActivityImage from '../models/PredefinedActivityImage.js';
import { checkAccess } from '../utils/userUtils.js';
import { Op } from 'sequelize';

import { devLog } from '../utils/logger.js';
class DiaryDateActivityService {

    async createActivity(userToken, clubId, data) {
        await checkAccess(userToken, clubId);
        const { activity, ...restData } = data;
        // Versuche, die PredefinedActivity robust zu finden:
        // 1) per übergebener ID
        // 2) per Name ODER Code (das Feld "activity" kann Kürzel oder Name sein)
        // 3) erst dann neu anlegen
        let predefinedActivity = null;

        if (data.predefinedActivityId) {
            predefinedActivity = await PredefinedActivity.findByPk(data.predefinedActivityId);
        }

        if (!predefinedActivity) {
            const normalized = (data.activity || '').trim();
            if (normalized) {
                predefinedActivity = await PredefinedActivity.findOne({
                    where: {
                        [Op.or]: [
                            { name: normalized },
                            { code: normalized }
                        ]
                    }
                });
            }
        }

        if (!predefinedActivity) {
            predefinedActivity = await PredefinedActivity.create({
                name: data.name || data.activity || '',
                code: data.code || (data.activity || ''),
                description: data.description || '',
                duration: data.duration && data.duration !== '' ? parseInt(data.duration) : null
            });
        }
        restData.predefinedActivityId = predefinedActivity.id; 
        
        // Bereinige duration-Feld für DiaryDateActivity
        if (restData.duration === '' || restData.duration === undefined) {
            restData.duration = null;
        } else if (typeof restData.duration === 'string') {
            restData.duration = parseInt(restData.duration);
        }
        
        const maxOrderId = await DiaryDateActivity.max('orderId', {
            where: { diaryDateId: data.diaryDateId } 
        });
        const newOrderId = maxOrderId !== null ? maxOrderId + 1 : 1;
        restData.orderId = newOrderId;
        return await DiaryDateActivity.create(restData);
    }

    async updateActivity(userToken, clubId, id, data) {
        await checkAccess(userToken, clubId);
        const activity = await DiaryDateActivity.findByPk(id);
        if (!activity) {
            throw new Error('Activity not found');
        }

        // Wenn customActivityName gesendet wird, müssen wir die PredefinedActivity behandeln
        if (data.customActivityName) {
            
            // Suche nach einer existierenden PredefinedActivity mit diesem Namen
            let predefinedActivity = await PredefinedActivity.findOne({ 
                where: { name: data.customActivityName } 
            });
            
            if (!predefinedActivity) {
                // Erstelle eine neue PredefinedActivity
                predefinedActivity = await PredefinedActivity.create({
                    name: data.customActivityName,
                    description: data.description || '',
                    duration: data.duration && data.duration !== '' ? parseInt(data.duration) : (activity.duration || null)
                });
            }
            
            // Setze die predefinedActivityId
            data.predefinedActivityId = predefinedActivity.id;
            
            // Entferne customActivityName aus den zu aktualisierenden Daten
            delete data.customActivityName;
        }

        return await activity.update(data);
    }

    async deleteActivity(userToken, clubId, id) {
        await checkAccess(userToken, clubId);
        const activity = await DiaryDateActivity.findByPk(id);
        if (!activity) {
            throw new Error('Activity not found');
        }
        return await activity.destroy();
    }

    async updateActivityOrder(userToken, clubId, id, newOrderId) {
        await checkAccess(userToken, clubId);
        const activity = await DiaryDateActivity.findByPk(id);
        if (!activity) {
            console.error('[DiaryDateActivityService::updateActivityOrder] - Activity not found, throwing error');
            throw new Error('Activity not found');
        }
        const currentOrderId = activity.orderId;
        if (newOrderId < currentOrderId) {
            await DiaryDateActivity.increment(
                { orderId: 1 },
                {
                    where: {
                        diaryDateId: activity.diaryDateId,
                        orderId: { [Op.gte]: newOrderId, [Op.lt]: currentOrderId },
                    },
                }
            );
        } else if (newOrderId > currentOrderId) {
            await DiaryDateActivity.decrement(
                { orderId: 1 },
                {
                    where: {
                        diaryDateId: activity.diaryDateId,
                        orderId: { [Op.lte]: newOrderId, [Op.gt]: currentOrderId },
                    },
                }
            );
        } else {
        }
        activity.orderId = newOrderId;
        const savedActivity = await activity.save();
        return savedActivity;
    }

    async getActivities(userToken, clubId, diaryDateId) {
        await checkAccess(userToken, clubId);
        const activities = await DiaryDateActivity.findAll({
            where: { diaryDateId },
            order: [['orderId', 'ASC']],
            include: [
                {
                    model: PredefinedActivity,
                    as: 'predefinedActivity',
                    include: [
                        {
                            model: PredefinedActivityImage,
                            as: 'images'
                        }
                    ]
                },
                {
                    model: GroupActivity, 
                    as: 'groupActivities',
                    include: [
                        {
                            model: Group,
                            as: 'groupsGroupActivity'
                        },
                        {
                            model: PredefinedActivity,
                            as: 'groupPredefinedActivity',
                            include: [
                                {
                                    model: PredefinedActivityImage,
                                    as: 'images'
                                }
                            ]
                        },
                    ],
                }
            ]
        });
        
        // Füge imageUrl zu jeder PredefinedActivity hinzu
        const activitiesWithImages = await Promise.all(activities.map(async activity => {
            // Konvertiere zu JSON und zurück, um alle Eigenschaften zu serialisieren
            const activityData = activity.toJSON();
            
            if (activityData.predefinedActivity) {
                // Hole alle Images aus der Datenbank
                const allImages = await PredefinedActivityImage.findAll({
                    where: { predefinedActivityId: activityData.predefinedActivity.id },
                    order: [['createdAt', 'ASC']]
                });
                
                // Konvertiere Images zu JSON und parse drawingData falls vorhanden
                const imagesWithParsedData = allImages.map(img => {
                    const imgData = img.toJSON();
                    if (imgData.drawingData) {
                        try {
                            imgData.drawingData = JSON.parse(imgData.drawingData);
                        } catch (error) {
                            console.error(`Image ${imgData.id}: Error parsing drawingData:`, error);
                        }
                    }
                    return imgData;
                });
                
                // Setze images Array
                activityData.predefinedActivity.images = imagesWithParsedData;
                
                const firstImage = allImages.length > 0 ? allImages[0] : null;
                
                // Füge Zeichnungsdaten hinzu, falls vorhanden
                // Priorität: 1. drawingData direkt auf PredefinedActivity, 2. drawingData aus firstImage
                if (activityData.predefinedActivity.drawingData) {
                    // drawingData ist bereits vorhanden (aus dem Model)
                    try {
                        if (typeof activityData.predefinedActivity.drawingData === 'string') {
                            activityData.predefinedActivity.drawingData = JSON.parse(activityData.predefinedActivity.drawingData);
                        }
                    } catch (error) {
                        console.error(`Activity ${activityData.predefinedActivity.id}: Error parsing drawingData:`, error);
                    }
                } else if (firstImage && firstImage.drawingData) {
                    try {
                        activityData.predefinedActivity.drawingData = JSON.parse(firstImage.drawingData);
                    } catch (error) {
                        console.error(`Activity ${activityData.predefinedActivity.id}: Error parsing drawingData from image:`, error);
                    }
                }
                
                if (firstImage) {
                    // Füge sowohl imageUrl als auch imageLink mit Image-ID hinzu
                    activityData.predefinedActivity.imageUrl = `/api/predefined-activities/${activityData.predefinedActivity.id}/image/${firstImage.id}`;
                    activityData.predefinedActivity.imageLink = `/api/predefined-activities/${activityData.predefinedActivity.id}/image/${firstImage.id}`;
                } else {
                    // Fallback: Verwende den Basis-Pfad ohne Image-ID
                    activityData.predefinedActivity.imageUrl = `/api/predefined-activities/${activityData.predefinedActivity.id}/image`;
                    activityData.predefinedActivity.imageLink = `/api/predefined-activities/${activityData.predefinedActivity.id}/image`;
                }
            }
            
            // Auch für GroupActivities
            if (activityData.groupActivities && activityData.groupActivities.length > 0) {
                const seenGroupActivityIds = new Set();
                activityData.groupActivities = activityData.groupActivities.filter(groupActivity => {
                    if (!groupActivity || groupActivity.id === undefined || groupActivity.id === null) {
                        return false;
                    }
                    if (seenGroupActivityIds.has(groupActivity.id)) {
                        return false;
                    }
                    seenGroupActivityIds.add(groupActivity.id);
                    return true;
                });
                for (const groupActivity of activityData.groupActivities) {
                    if (groupActivity.groupPredefinedActivity) {
                        // Hole alle Images aus der Datenbank
                        const allImages = await PredefinedActivityImage.findAll({
                            where: { predefinedActivityId: groupActivity.groupPredefinedActivity.id },
                            order: [['createdAt', 'ASC']]
                        });
                        
                        // Konvertiere Images zu JSON und parse drawingData falls vorhanden
                        const imagesWithParsedData = allImages.map(img => {
                            const imgData = img.toJSON();
                            if (imgData.drawingData) {
                                try {
                                    imgData.drawingData = JSON.parse(imgData.drawingData);
                                } catch (error) {
                                    console.error(`Image ${imgData.id}: Error parsing drawingData:`, error);
                                }
                            }
                            return imgData;
                        });
                        
                        // Setze images Array
                        groupActivity.groupPredefinedActivity.images = imagesWithParsedData;
                        
                        const firstImage = allImages.length > 0 ? allImages[0] : null;
                        
                        // Füge Zeichnungsdaten hinzu, falls vorhanden
                        // Priorität: 1. drawingData direkt auf PredefinedActivity, 2. drawingData aus firstImage
                        if (groupActivity.groupPredefinedActivity.drawingData) {
                            try {
                                if (typeof groupActivity.groupPredefinedActivity.drawingData === 'string') {
                                    groupActivity.groupPredefinedActivity.drawingData = JSON.parse(groupActivity.groupPredefinedActivity.drawingData);
                                }
                            } catch (error) {
                                console.error(`GroupActivity ${groupActivity.groupPredefinedActivity.id}: Error parsing drawingData:`, error);
                            }
                        } else if (firstImage && firstImage.drawingData) {
                            try {
                                groupActivity.groupPredefinedActivity.drawingData = JSON.parse(firstImage.drawingData);
                            } catch (error) {
                                console.error(`GroupActivity ${groupActivity.groupPredefinedActivity.id}: Error parsing drawingData from image:`, error);
                            }
                        }
                        
                        if (firstImage) {
                            groupActivity.groupPredefinedActivity.imageUrl = `/api/predefined-activities/${groupActivity.groupPredefinedActivity.id}/image/${firstImage.id}`;
                            groupActivity.groupPredefinedActivity.imageLink = `/api/predefined-activities/${groupActivity.groupPredefinedActivity.id}/image/${firstImage.id}`;
                        } else {
                            groupActivity.groupPredefinedActivity.imageUrl = `/api/predefined-activities/${groupActivity.groupPredefinedActivity.id}/image`;
                            groupActivity.groupPredefinedActivity.imageLink = `/api/predefined-activities/${groupActivity.groupPredefinedActivity.id}/image`;
                        }
                    }
                }
            }
            return activityData;
        }));
        return activitiesWithImages;
    }

    async addGroupActivity(userToken, clubId, diaryDateId, groupId, activity, predefinedActivityId = null, timeblockId = null) {
        await checkAccess(userToken, clubId);
        let diaryDateActivity;
        
        if (timeblockId) {
            // Verwende die spezifische Zeitblock-ID, falls angegeben
            diaryDateActivity = await DiaryDateActivity.findOne({
                where: {
                    id: timeblockId,
                    diaryDateId,
                    isTimeblock: true,
                }
            });
        } else {
            // Fallback: Verwende den letzten Zeitblock
            diaryDateActivity = await DiaryDateActivity.findOne({
                where: {
                    diaryDateId,
                    isTimeblock: true,
                },
                order: [['order_id', 'DESC']],
                limit: 1
            });
        }
        
        if (!diaryDateActivity) {
            console.error('[DiaryDateActivityService::addGroupActivity] Activity not found');
            throw new Error('Activity not found');
        }
        const group = await Group.findByPk(groupId);
        if (!group) {
            console.error('[DiaryDateActivityService::addGroupActivity] Group not found:', groupId);
            throw new Error('Group not found');
        }
        
        if (group.diaryDateId !== diaryDateActivity.diaryDateId) {
            console.error('[DiaryDateActivityService::addGroupActivity] Group and date don\'t fit');
            console.error('Group diaryDateId:', group.diaryDateId, 'Activity diaryDateId:', diaryDateActivity.diaryDateId);
            throw new Error('Group isn\'t related to date');
        }
        
        let predefinedActivity = null;
        
        // 1. Versuche zuerst, die PredefinedActivity per ID zu finden
        if (predefinedActivityId) {
            predefinedActivity = await PredefinedActivity.findByPk(predefinedActivityId);
        }
        
        // 2. Falls nicht gefunden, suche nach Name oder Code
        if (!predefinedActivity) {
            const normalized = (activity || '').trim();
            if (normalized) {
                predefinedActivity = await PredefinedActivity.findOne({
                    where: {
                        [Op.or]: [
                            { name: normalized },
                            { code: normalized }
                        ]
                    }
                });
            }
        }
        
        // 3. Falls immer noch nicht gefunden, erstelle eine neue
        if (!predefinedActivity) {
            predefinedActivity = await PredefinedActivity.create({
                name: activity || '',
                code: activity || '',
            });
        }
        
        devLog(predefinedActivity);
        const activityData = {
            diaryDateActivity: diaryDateActivity.id,
            groupId: groupId,
            customActivity: predefinedActivity.id
        }
        devLog(activityData);
        return await GroupActivity.create(activityData);
    }

    async updateGroupActivity(userToken, clubId, groupActivityId, predefinedActivityId) {
        await checkAccess(userToken, clubId);
        const groupActivity = await GroupActivity.findByPk(groupActivityId);
        if (!groupActivity) {
            throw new Error('Group activity not found');
        }
        
        // Prüfe, ob die PredefinedActivity existiert
        const predefinedActivity = await PredefinedActivity.findByPk(predefinedActivityId);
        if (!predefinedActivity) {
            throw new Error('Predefined activity not found');
        }
        
        // Aktualisiere die customActivity (die auf die PredefinedActivity verweist)
        groupActivity.customActivity = predefinedActivityId;
        return await groupActivity.save();
    }

    async deleteGroupActivity(userToken, clubId, groupActivityId) {
        await checkAccess(userToken, clubId);
        const groupActivity = await GroupActivity.findByPk(groupActivityId);
        if (!groupActivity) {
            throw new Error('Group activity not found');
        }
        return await groupActivity.destroy();
    }
}

export default new DiaryDateActivityService();
