/**
 * Enhanced Metadata Enrichment API Routes
 *
 * Comprehensive API endpoints for controlling the advanced metadata enrichment system.
 * Provides granular control, monitoring, and configuration capabilities.
 */ import { Router } from "express";
import { getEnhancedMetadataEnrichmentService } from "./enhancedMetadataEnrichmentService.js";
import { getAdvancedMetadataEngine } from "./advancedMetadataEngine.js";
import { getDatabase } from "./database.js";
import { serverLogger } from "../utils/serverLogger.js";
import { getErrorMessage } from "../utils/errorUtils.js";
import * as path from "path";
export function createEnhancedMetadataRoutes() {
    const router = Router();
    // Get service status and statistics
    router.get("/status", (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            const stats = service.getStats();
            res.json({
                status: "online",
                isRunning: stats.isRunning,
                isPaused: stats.isPaused,
                currentProgress: stats.currentProgress,
                queueStats: stats.queueStats,
                processingStats: stats.processingStats,
                sessionStats: stats.sessionStats,
                lastRun: stats.lastRun,
                nextScheduledRun: stats.nextScheduledRun,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get enrichment status", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get status",
                details: getErrorMessage(error)
            });
        }
    });
    // Get current configuration
    router.get("/config", (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            const config = service.getConfig();
            res.json({
                config,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get enrichment config", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get configuration",
                details: getErrorMessage(error)
            });
        }
    });
    // Update configuration
    router.post("/config", (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            const newConfig = req.body;
            // Validate configuration
            if (!newConfig || typeof newConfig !== "object") {
                return res.status(400).json({
                    error: "Invalid configuration format"
                });
            }
            service.updateConfig(newConfig);
            const updatedConfig = service.getConfig();
            serverLogger.info("Enrichment configuration updated", {
                enabled: updatedConfig.enabled,
                batchSize: updatedConfig.batchSize,
                sources: updatedConfig.sources
            });
            res.json({
                success: true,
                config: updatedConfig,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to update enrichment config", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to update configuration",
                details: getErrorMessage(error)
            });
        }
    });
    // Start the enrichment service
    router.post("/start", async (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            await service.start();
            res.json({
                success: true,
                message: "Enhanced metadata enrichment service started",
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to start enrichment service", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to start service",
                details: getErrorMessage(error)
            });
        }
    });
    // Stop the enrichment service
    router.post("/stop", async (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            await service.stop();
            res.json({
                success: true,
                message: "Enhanced metadata enrichment service stopped",
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to stop enrichment service", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to stop service",
                details: getErrorMessage(error)
            });
        }
    });
    // Pause processing
    router.post("/pause", (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            service.pause();
            res.json({
                success: true,
                message: "Processing paused",
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to pause service", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to pause service",
                details: getErrorMessage(error)
            });
        }
    });
    // Resume processing
    router.post("/resume", (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            service.resume();
            res.json({
                success: true,
                message: "Processing resumed",
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to resume service", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to resume service",
                details: getErrorMessage(error)
            });
        }
    });
    // Scan library for tracks needing enrichment
    router.post("/scan", async (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            const result = await service.scanLibrary();
            res.json({
                success: true,
                message: "Library scan completed",
                result,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to scan library", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to scan library",
                details: getErrorMessage(error)
            });
        }
    });
    // Enrich specific tracks
    router.post("/enrich", async (req, res)=>{
        try {
            const { trackPaths, priority } = req.body;
            if (!Array.isArray(trackPaths) || trackPaths.length === 0) {
                return res.status(400).json({
                    error: "trackPaths must be a non-empty array"
                });
            }
            // Validate track paths
            const validPaths = trackPaths.filter((path)=>typeof path === "string" && path.length > 0);
            if (validPaths.length === 0) {
                return res.status(400).json({
                    error: "No valid track paths provided"
                });
            }
            const service = getEnhancedMetadataEnrichmentService();
            const result = await service.enrichTracks(validPaths, priority || 100);
            res.json({
                success: true,
                message: `Added ${result.added} tracks to enrichment queue`,
                result,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to enrich tracks", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to enrich tracks",
                details: getErrorMessage(error)
            });
        }
    });
    // Enrich single track with detailed response
    router.post("/enrich/:trackId", async (req, res)=>{
        try {
            const { trackId } = req.params;
            const trackPath = decodeURIComponent(trackId);
            // Basic path validation
            if (!trackPath || trackPath.length === 0) {
                return res.status(400).json({
                    error: "Invalid track path"
                });
            }
            const service = getEnhancedMetadataEnrichmentService();
            const result = await service.enrichSingleTrack(trackPath);
            res.json({
                success: result.success,
                trackPath,
                result,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to enrich single track", {
                trackId: req.params.trackId,
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to enrich track",
                details: getErrorMessage(error)
            });
        }
    });
    // Run full library enrichment
    router.post("/enrich/full", async (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            await service.runFullLibraryEnrichment();
            res.json({
                success: true,
                message: "Full library enrichment completed",
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to run full library enrichment", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to run full enrichment",
                details: getErrorMessage(error)
            });
        }
    });
    // Get queue information
    router.get("/queue", (req, res)=>{
        try {
            const engine = getAdvancedMetadataEngine();
            const queueStats = engine.getQueueStats();
            // Get recent queue items for debugging
            const db = getDatabase();
            const recentItems = db.db.prepare(`
        SELECT track_path, priority, attempts, status, error, created_at, updated_at
        FROM metadata_enrichment_queue
        ORDER BY priority DESC, created_at DESC
        LIMIT 50
      `).all();
            res.json({
                stats: queueStats,
                recentItems: recentItems.map((item)=>({
                        ...item,
                        trackName: path.basename(item.track_path)
                    })),
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get queue information", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get queue information",
                details: getErrorMessage(error)
            });
        }
    });
    // Clear completed queue items
    router.post("/queue/clear", async (req, res)=>{
        try {
            const engine = getAdvancedMetadataEngine();
            const cleared = await engine.clearCompletedQueue();
            res.json({
                success: true,
                message: `Cleared ${cleared} completed queue items`,
                cleared,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to clear queue", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to clear queue",
                details: getErrorMessage(error)
            });
        }
    });
    // Get enrichment results for a specific track
    router.get("/results/:trackId", (req, res)=>{
        try {
            const { trackId } = req.params;
            const trackPath = decodeURIComponent(trackId);
            const db = getDatabase();
            // Get enrichment result
            const result = db.db.prepare(`
        SELECT * FROM metadata_enrichment_results WHERE track_path = ?
      `).get(trackPath);
            if (!result) {
                return res.status(404).json({
                    error: "No enrichment results found for this track"
                });
            }
            // Get all source matches
            const sources = db.db.prepare(`
        SELECT * FROM metadata_enrichment_sources 
        WHERE track_path = ?
        ORDER BY confidence DESC
      `).all(trackPath);
            res.json({
                trackPath,
                result: {
                    ...result,
                    sources: sources.map((source)=>({
                            ...source,
                            raw_data: source.raw_data ? JSON.parse(source.raw_data) : null
                        }))
                },
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get enrichment results", {
                trackId: req.params.trackId,
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get enrichment results",
                details: getErrorMessage(error)
            });
        }
    });
    // Get metadata sources for a track (what sources provided what data)
    router.get("/sources/:trackId", (req, res)=>{
        try {
            const { trackId } = req.params;
            const trackPath = decodeURIComponent(trackId);
            const db = getDatabase();
            const sources = db.db.prepare(`
        SELECT source, confidence, title, artist, album, genre, year, created_at
        FROM metadata_enrichment_sources 
        WHERE track_path = ?
        ORDER BY confidence DESC, created_at DESC
      `).all(trackPath);
            if (sources.length === 0) {
                return res.status(404).json({
                    error: "No metadata sources found for this track"
                });
            }
            res.json({
                trackPath,
                trackName: path.basename(trackPath),
                sources,
                count: sources.length,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get metadata sources", {
                trackId: req.params.trackId,
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get metadata sources",
                details: getErrorMessage(error)
            });
        }
    });
    // Get tracks with low confidence metadata (need manual review)
    router.get("/low-confidence", (req, res)=>{
        try {
            const { limit = 50, offset = 0, threshold = 0.7 } = req.query;
            const db = getDatabase();
            const tracks = db.db.prepare(`
        SELECT r.track_path, r.confidence, r.final_artist, r.final_title, r.final_album,
               r.errors, r.sources_used, r.updated_at,
               t.artist as original_artist, t.title as original_title, t.album as original_album
        FROM metadata_enrichment_results r
        LEFT JOIN tracks t ON r.track_path = t.path
        WHERE r.confidence < ?
        ORDER BY r.confidence ASC, r.updated_at DESC
        LIMIT ? OFFSET ?
      `).all(Number(threshold), Number(limit), Number(offset));
            const totalCount = db.db.prepare(`
        SELECT COUNT(*) as count
        FROM metadata_enrichment_results
        WHERE confidence < ?
      `).get(Number(threshold));
            res.json({
                tracks: tracks.map((track)=>({
                        ...track,
                        trackName: path.basename(track.track_path),
                        sources_used: track.sources_used ? track.sources_used.split(",") : [],
                        errors: track.errors ? track.errors.split("; ") : []
                    })),
                pagination: {
                    limit: Number(limit),
                    offset: Number(offset),
                    total: totalCount.count
                },
                threshold: Number(threshold),
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get low confidence tracks", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get low confidence tracks",
                details: getErrorMessage(error)
            });
        }
    });
    // Export enrichment report
    router.get("/report", async (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            const report = await service.exportEnrichmentReport();
            res.json({
                success: true,
                report,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to export enrichment report", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to export report",
                details: getErrorMessage(error)
            });
        }
    });
    // Get API key status and configuration
    router.get("/api-keys", (req, res)=>{
        try {
            const service = getEnhancedMetadataEnrichmentService();
            const config = service.getConfig();
            res.json({
                acoustid: {
                    configured: !!config.apiKeys.acoustid,
                    enabled: config.sources.acoustid
                },
                lastfm: {
                    configured: !!config.apiKeys.lastfm,
                    enabled: config.sources.lastfm
                },
                musicbrainz: {
                    configured: true,
                    enabled: config.sources.musicbrainz
                },
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to get API key status", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to get API key status",
                details: getErrorMessage(error)
            });
        }
    });
    // Run comprehensive test suite
    router.post("/test", async (req, res)=>{
        try {
            const { createTestClient } = await import("./metadataTestClient.js");
            const appState = req.appState || req.app.locals.appState;
            if (!appState) {
                return res.status(500).json({
                    error: "AppState not available"
                });
            }
            const client = createTestClient(appState);
            // Run tests in background and return immediately
            client.runAllTests().catch((error)=>{
                serverLogger.error("Background test execution failed", {
                    error: getErrorMessage(error)
                });
            });
            res.json({
                success: true,
                message: "Test suite started. Check server logs for detailed results.",
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to start test suite", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to start test suite",
                details: getErrorMessage(error)
            });
        }
    });
    // Test connectivity to external services
    router.post("/test-connectivity", async (req, res)=>{
        try {
            const results = {
                musicbrainz: {
                    status: "unknown",
                    latency: 0,
                    error: null
                },
                acoustid: {
                    status: "unknown",
                    latency: 0,
                    error: null
                },
                lastfm: {
                    status: "unknown",
                    latency: 0,
                    error: null
                }
            };
            // Test MusicBrainz
            try {
                const start = Date.now();
                const controller = new AbortController();
                const timeoutId = setTimeout(()=>controller.abort(), 5000);
                const response = await fetch("https://musicbrainz.org/ws/2/recording?query=artist:Beatles&limit=1", {
                    headers: {
                        "User-Agent": "SOUND-Metadata-Test/1.0.0"
                    },
                    signal: controller.signal
                });
                clearTimeout(timeoutId);
                results.musicbrainz.latency = Date.now() - start;
                results.musicbrainz.status = response.ok ? "online" : "error";
                if (!response.ok) results.musicbrainz.error = `HTTP ${response.status}`;
            } catch (error) {
                results.musicbrainz.status = "offline";
                results.musicbrainz.error = getErrorMessage(error);
            }
            // Test AcoustID if API key is configured
            const service = getEnhancedMetadataEnrichmentService();
            const config = service.getConfig();
            if (config.apiKeys.acoustid) {
                try {
                    const start = Date.now();
                    const controller = new AbortController();
                    const timeoutId = setTimeout(()=>controller.abort(), 5000);
                    const response = await fetch("https://api.acoustid.org/v2/lookup", {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/x-www-form-urlencoded"
                        },
                        body: new URLSearchParams({
                            client: config.apiKeys.acoustid,
                            duration: "180",
                            fingerprint: "test",
                            meta: "recordings"
                        }),
                        signal: controller.signal
                    });
                    clearTimeout(timeoutId);
                    results.acoustid.latency = Date.now() - start;
                    results.acoustid.status = "online"; // AcoustID returns errors for invalid fingerprints, which is expected
                } catch (error) {
                    results.acoustid.status = "offline";
                    results.acoustid.error = getErrorMessage(error);
                }
            } else {
                results.acoustid.status = "not_configured";
                results.acoustid.error = "API key not configured";
            }
            // Test Last.fm if API key is configured
            if (config.apiKeys.lastfm) {
                try {
                    const start = Date.now();
                    const controller = new AbortController();
                    const timeoutId = setTimeout(()=>controller.abort(), 5000);
                    const response = await fetch(`https://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=Beatles&api_key=${config.apiKeys.lastfm}&format=json`, {
                        signal: controller.signal
                    });
                    clearTimeout(timeoutId);
                    results.lastfm.latency = Date.now() - start;
                    results.lastfm.status = response.ok ? "online" : "error";
                    if (!response.ok) results.lastfm.error = `HTTP ${response.status}`;
                } catch (error) {
                    results.lastfm.status = "offline";
                    results.lastfm.error = getErrorMessage(error);
                }
            } else {
                results.lastfm.status = "not_configured";
                results.lastfm.error = "API key not configured";
            }
            res.json({
                success: true,
                results,
                timestamp: Date.now()
            });
        } catch (error) {
            serverLogger.error("Failed to test connectivity", {
                error: getErrorMessage(error)
            });
            res.status(500).json({
                error: "Failed to test connectivity",
                details: getErrorMessage(error)
            });
        }
    });
    return router;
}

//# sourceMappingURL=enhancedMetadataRoutes.js.map