import PredefinedActivity from '../models/PredefinedActivity.js';
import DiaryDateActivity from '../models/DiaryDateActivity.js';
import GroupActivity from '../models/GroupActivity.js';
import PredefinedActivityImage from '../models/PredefinedActivityImage.js';
import sequelize from '../database.js';
import { Op } from 'sequelize';
import { normalizeStoredDrawingData } from '../utils/drawingData.js';

import { devLog } from '../utils/logger.js';
class PredefinedActivityService {
    async createPredefinedActivity(data) {
        return await PredefinedActivity.create({
            name: data.name,
            code: data.code,
            description: data.description,
            durationText: data.durationText,
            duration: data.duration,
            imageLink: data.imageLink,
            excludeFromStats: Boolean(data.excludeFromStats),
            drawingData: normalizeStoredDrawingData(data.drawingData),
        });
    }

    async updatePredefinedActivity(id, data) {
        const activity = await PredefinedActivity.findByPk(id);
        if (!activity) {
            throw new Error('Predefined activity not found');
        }
        return await activity.update({
            name: data.name,
            code: data.code,
            description: data.description,
            durationText: data.durationText,
            duration: data.duration,
            imageLink: data.imageLink,
            excludeFromStats: Boolean(data.excludeFromStats),
            drawingData: normalizeStoredDrawingData(data.drawingData),
        });
    }

    async getAllPredefinedActivities(scope = 'all') {
        const where = {};
        if (scope === 'standard') {
            where.excludeFromStats = true;
        } else if (scope === 'custom') {
            where.excludeFromStats = false;
        }

        return await PredefinedActivity.findAll({
            where,
            order: [
                [sequelize.literal('code IS NULL'), 'ASC'], // Non-null codes first
                ['code', 'ASC'],
                ['name', 'ASC'],
            ],
        });
    }

    async getPredefinedActivityById(id) {
        const activity = await PredefinedActivity.findByPk(id);
        if (!activity) {
            throw new Error('Predefined activity not found');
        }
        return activity;
    }

    async searchPredefinedActivities(query, limit = 20) {
        const q = (query || '').trim();
        if (!q || q.length < 2) {
            return [];
        }
        
        // Intelligente Suche: Teile den Query in einzelne Begriffe auf
        const searchTerms = q.split(/\s+/).filter(term => term.length > 0);
        
        if (searchTerms.length === 0) {
            return [];
        }
        
        // Hole alle Aktivitäten mit Kürzeln
        const allActivities = await PredefinedActivity.findAll({
            where: {
                code: { [Op.ne]: null } // Nur Aktivitäten mit Kürzel
            },
            order: [
                [sequelize.literal('code IS NULL'), 'ASC'],
                ['code', 'ASC'],
                ['name', 'ASC'],
            ],
            limit: 1000 // Höhere Grenze für Filterung
        });
        
        // Filtere die Ergebnisse, um nur die zu finden, die ALLE Begriffe enthalten
        const filteredResults = allActivities.filter(activity => {
            const code = (activity.code || '').toLowerCase();
            
            // Prüfe, ob alle Suchbegriffe im Kürzel enthalten sind
            return searchTerms.every(term => {
                const normalizedTerm = term.toLowerCase();
                return code.includes(normalizedTerm);
            });
        });
        
        // Begrenze die Ergebnisse
        return filteredResults.slice(0, Math.min(parseInt(limit || 20, 10), 50));
    }

    async mergeActivities(sourceId, targetId) {
        if (!sourceId || !targetId) throw new Error('sourceId and targetId are required');
        if (Number(sourceId) === Number(targetId)) throw new Error('sourceId and targetId must differ');

        const tx = await sequelize.transaction();
        try {
            const source = await PredefinedActivity.findByPk(sourceId, { transaction: tx });
            const target = await PredefinedActivity.findByPk(targetId, { transaction: tx });
            if (!source) throw new Error('Source activity not found');
            if (!target) throw new Error('Target activity not found');

            // Reassign references
            await DiaryDateActivity.update(
                { predefinedActivityId: targetId },
                { where: { predefinedActivityId: sourceId }, transaction: tx }
            );

            await GroupActivity.update(
                { customActivity: targetId },
                { where: { customActivity: sourceId }, transaction: tx }
            );

            await PredefinedActivityImage.update(
                { predefinedActivityId: targetId },
                { where: { predefinedActivityId: sourceId }, transaction: tx }
            );

            // Finally delete source
            await source.destroy({ transaction: tx });

            await tx.commit();
            return { ok: true };
        } catch (err) {
            await tx.rollback();
            console.error('[PredefinedActivityService::mergeActivities] - Error:', err);
            throw err;
        }
    }

    async deduplicateActivities() {
        const all = await PredefinedActivity.findAll();
        const nameToActivities = new Map();
        for (const activity of all) {
            const key = (activity.name || '').trim().toLowerCase();
            if (!key) continue;
            if (!nameToActivities.has(key)) nameToActivities.set(key, []);
            nameToActivities.get(key).push(activity);
        }
        let mergedCount = 0;
        let groupCount = 0;
        for (const list of nameToActivities.values()) {
            if (!list || list.length <= 1) continue;
            groupCount++;
            // Stable target: kleinste ID
            list.sort((a, b) => a.id - b.id);
            const target = list[0];
            for (const src of list.slice(1)) {
                await this.mergeActivities(src.id, target.id);
                mergedCount++;
            }
        }
        return { mergedCount, groupCount };
    }
}

export default new PredefinedActivityService();
