import db from '../db';

interface ImportanceFactors {
    changePercentage: number;     // 0-100
    keywordMatches: number;       // Anzahl wichtiger Keywords
    isMainContent: boolean;       // Haupt- vs. Sidebar-Content
    isRecurringPattern: boolean;  // Wiederkehrendes Muster (z.B. täglich)
    contentLength: number;        // Länge des geänderten Contents
}

/**
 * Calculate importance score for a change (0-100)
 * Higher scores indicate more significant changes
 */
export function calculateImportanceScore(factors: ImportanceFactors): number {
    let score = 0;

    // 1. Change Percentage (max 40 points)
    // - Small changes (<5%) = low importance
    // - Medium changes (5-20%) = medium importance  
    // - Large changes (>20%) = high importance
    if (factors.changePercentage < 5) {
        score += factors.changePercentage * 2; // 0-10 points
    } else if (factors.changePercentage < 20) {
        score += 10 + (factors.changePercentage - 5) * 1.5; // 10-32.5 points
    } else {
        score += Math.min(32.5 + (factors.changePercentage - 20) * 0.5, 40); // 32.5-40 points
    }

    // 2. Keyword matches (max 30 points)
    // Each keyword match adds importance
    score += Math.min(factors.keywordMatches * 10, 30);

    // 3. Main content bonus (20 points)
    // Changes in main content area are more important than sidebar/footer
    if (factors.isMainContent) {
        score += 20;
    }

    // 4. Content length consideration (max 10 points)
    // Longer changes tend to be more significant
    if (factors.contentLength > 500) {
        score += 10;
    } else if (factors.contentLength > 100) {
        score += 5;
    } else if (factors.contentLength > 50) {
        score += 2;
    }

    // 5. Recurring pattern penalty (-15 points)
    // If changes happen at the same time pattern, they're likely automated/less important
    if (factors.isRecurringPattern) {
        score -= 15;
    }

    // Clamp to 0-100
    return Math.max(0, Math.min(100, Math.round(score)));
}

/**
 * Check if monitor has a recurring change pattern
 * (changes occurring at similar times/intervals)
 */
export async function detectRecurringPattern(monitorId: string): Promise<boolean> {
    try {
        // Get last 10 changes for this monitor
        const result = await db.query(
            `SELECT checked_at 
       FROM snapshots 
       WHERE monitor_id = $1 AND has_changes = true
       ORDER BY checked_at DESC
       LIMIT 10`,
            [monitorId]
        );

        if (result.rows.length < 3) {
            return false; // Not enough data to detect pattern
        }

        const timestamps = result.rows.map((r: any) => new Date(r.checked_at));

        // Check for same-hour pattern (changes always at similar hour)
        const hours = timestamps.map((t: Date) => t.getHours());
        const hourCounts: Record<number, number> = {};
        hours.forEach((h: number) => {
            hourCounts[h] = (hourCounts[h] || 0) + 1;
        });

        // If more than 60% of changes happen at the same hour, it's a pattern
        const maxHourCount = Math.max(...Object.values(hourCounts));
        if (maxHourCount / timestamps.length > 0.6) {
            return true;
        }

        // Check for regular interval pattern
        if (timestamps.length >= 3) {
            const intervals: number[] = [];
            for (let i = 0; i < timestamps.length - 1; i++) {
                intervals.push(timestamps[i].getTime() - timestamps[i + 1].getTime());
            }

            // Check if intervals are consistent (within 10% variance)
            const avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;
            const variance = intervals.map(i => Math.abs(i - avgInterval) / avgInterval);
            const avgVariance = variance.reduce((a, b) => a + b, 0) / variance.length;

            if (avgVariance < 0.1) {
                return true; // Changes happen at regular intervals
            }
        }

        return false;
    } catch (error) {
        console.error('[Importance] Error detecting pattern:', error);
        return false;
    }
}

/**
 * Simple heuristic to detect if change is in main content area
 * Based on common HTML patterns
 */
export function isMainContentChange(htmlDiff: string): boolean {
    const mainContentPatterns = [
        '<main', '</main>',
        '<article', '</article>',
        'class="content"', 'class="main"',
        'id="content"', 'id="main"',
        '<h1', '<h2', '<h3',
        '<p>', '</p>'
    ];

    const sidebarPatterns = [
        '<aside', '</aside>',
        '<nav', '</nav>',
        '<footer', '</footer>',
        '<header', '</header>',
        'class="sidebar"', 'class="nav"',
        'class="footer"', 'class="header"'
    ];

    const lowerDiff = htmlDiff.toLowerCase();

    let mainContentScore = 0;
    let sidebarScore = 0;

    mainContentPatterns.forEach(pattern => {
        if (lowerDiff.includes(pattern.toLowerCase())) {
            mainContentScore++;
        }
    });

    sidebarPatterns.forEach(pattern => {
        if (lowerDiff.includes(pattern.toLowerCase())) {
            sidebarScore++;
        }
    });

    return mainContentScore >= sidebarScore;
}

/**
 * Get importance level label from score
 */
export function getImportanceLevel(score: number): 'high' | 'medium' | 'low' {
    if (score >= 70) return 'high';
    if (score >= 40) return 'medium';
    return 'low';
}

/**
 * Calculate importance for a specific change
 */
export async function calculateChangeImportance(
    monitorId: string,
    changePercentage: number,
    keywordMatches: number,
    diffContent: string
): Promise<number> {
    const isRecurring = await detectRecurringPattern(monitorId);
    const isMainContent = isMainContentChange(diffContent);

    return calculateImportanceScore({
        changePercentage,
        keywordMatches,
        isMainContent,
        isRecurringPattern: isRecurring,
        contentLength: diffContent.length
    });
}
