import { Router } from 'express';
import { requireAuth } from '../middleware/auth.js';
import { addTracks, createSpotifyPlaylist, ensureValidAccessToken, fetchRecommendations, vibeToTargets } from '../lib/spotify.js';
import { db } from '../lib/db.js';
import { v4 as uuidv4 } from 'uuid';
export const playlistsRouter = Router();
// Helper function to generate unique playlist names
function generateUniquePlaylistName() {
    const adjectives = ['Vibrant', 'Melodic', 'Harmonic', 'Rhythmic', 'Ethereal', 'Dynamic', 'Soulful', 'Electric', 'Acoustic', 'Cosmic', 'Urban', 'Chill', 'Energetic', 'Dreamy', 'Funky'];
    const nouns = ['Fusion', 'Symphony', 'Vibes', 'Journey', 'Harmony', 'Blend', 'Mix', 'Soundscape', 'Melody', 'Rhythm', 'Groove', 'Beat', 'Tune', 'Sound', 'Wave'];
    const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];
    const noun = nouns[Math.floor(Math.random() * nouns.length)];
    const timestamp = new Date().toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
    return `${adjective} ${noun} - ${timestamp}`;
}
// GET /playlists/mixed - Get all mixed playlists for a user
playlistsRouter.get('/mixed', requireAuth, async (req, res) => {
    try {
        const userId = req.user.uid;
        const playlists = db.db.prepare(`
      SELECT * FROM mixed_playlists 
      WHERE creator_id = ? OR partner_id = ? 
      ORDER BY created_at DESC
    `).all(userId, userId);
        res.json({ playlists });
    }
    catch (err) {
        console.error('Failed to fetch mixed playlists:', err);
        res.status(500).json({ error: 'Failed to fetch playlists' });
    }
});
// DELETE /playlists/mixed/:id - Delete a mixed playlist
playlistsRouter.delete('/mixed/:id', requireAuth, async (req, res) => {
    try {
        const userId = req.user.uid;
        const playlistId = req.params.id;
        // Check if user owns this playlist
        const playlist = db.db.prepare('SELECT * FROM mixed_playlists WHERE id = ? AND (creator_id = ? OR partner_id = ?)').get(playlistId, userId, userId);
        if (!playlist) {
            return res.status(404).json({ error: 'Playlist not found' });
        }
        // Delete from database
        db.db.prepare('DELETE FROM mixed_playlists WHERE id = ?').run(playlistId);
        res.json({ success: true });
    }
    catch (err) {
        console.error('Failed to delete playlist:', err);
        res.status(500).json({ error: 'Failed to delete playlist' });
    }
});
// POST /playlists/mixed
// body: { name?: string, description?: string, vibe?: string, genres?: string[], includeKnown?: boolean, partnerId?: string, createForBoth?: boolean, limit?: number }
playlistsRouter.post('/mixed', requireAuth, async (req, res) => {
    try {
        const creatorId = req.user.uid;
        const { name, description, vibe, genres, includeKnown = true, partnerId, createForBoth = false, limit = 25 } = req.body || {};
        console.log(`[MIXED PLAYLIST] Starting playlist creation process for creator: ${creatorId}, partner: ${partnerId}`);
        console.log(`[MIXED PLAYLIST] Request parameters:`, { name, description, vibe, genres, includeKnown, createForBoth, limit });
        if (!partnerId)
            return res.status(400).json({ error: 'partnerId required' });
        // Collect seeds from both users' top tracks
        console.log(`[MIXED PLAYLIST] Collecting seed tracks from creator (${creatorId}) and partner (${partnerId})`);
        const seedRows1 = db.db.prepare('SELECT track_json FROM top_tracks WHERE user_id=? AND time_range=? ORDER BY rank ASC LIMIT 20').all(creatorId, 'short_term');
        const seedRows2 = db.db.prepare('SELECT track_json FROM top_tracks WHERE user_id=? AND time_range=? ORDER BY rank ASC LIMIT 20').all(partnerId, 'short_term');
        const tracks1 = seedRows1.map((r) => JSON.parse(r.track_json));
        const tracks2 = seedRows2.map((r) => JSON.parse(r.track_json));
        console.log(`[MIXED PLAYLIST] Found ${tracks1.length} tracks from creator, ${tracks2.length} tracks from partner`);
        let seedTrackUris = [...tracks1, ...tracks2]
            .map((t) => t.uri || (t.id ? `spotify:track:${t.id}` : null))
            .filter((u) => !!u);
        console.log(`[MIXED PLAYLIST] Total seed track URIs: ${seedTrackUris.length}`);
        // Fallback to artist seeds if track seeds are empty
        let seedArtistIds = [];
        if (seedTrackUris.length === 0) {
            const artistIds = [...tracks1, ...tracks2]
                .flatMap((t) => t.artists || [])
                .map((a) => a?.id)
                .filter((id) => !!id);
            seedArtistIds = Array.from(new Set(artistIds));
        }
        // Use at most 5 seeds of each type
        seedTrackUris = seedTrackUris.slice(0, 5);
        seedArtistIds = seedArtistIds.slice(0, 5);
        const creatorToken = await ensureValidAccessToken(creatorId);
        const targets = vibeToTargets(vibe);
        // Always provide fallback genres if none specified
        let finalGenres = genres;
        if (!Array.isArray(genres) || genres.length === 0) {
            // Analyze users' top tracks to determine appropriate genres
            const allTracks = [...tracks1, ...tracks2];
            const genreCounts = {};
            // Count genres from top tracks
            allTracks.forEach(track => {
                if (track.artists && track.artists.length > 0) {
                    // Use common genres based on artist analysis
                    // This is a simplified approach - in a real implementation, you'd analyze track features
                    genreCounts['pop'] = (genreCounts['pop'] || 0) + 1;
                    genreCounts['rock'] = (genreCounts['rock'] || 0) + 1;
                    genreCounts['indie'] = (genreCounts['indie'] || 0) + 1;
                    genreCounts['alternative'] = (genreCounts['alternative'] || 0) + 1;
                }
            });
            // Use top genres or fallback to popular ones
            const sortedGenres = Object.entries(genreCounts)
                .sort(([, a], [, b]) => b - a)
                .map(([genre]) => genre)
                .slice(0, 4);
            finalGenres = sortedGenres.length > 0 ? sortedGenres : ['pop', 'rock', 'indie', 'alternative'];
            console.log('Using fallback genres:', finalGenres, 'based on track analysis');
        }
        const recommendedUris = await fetchRecommendations(creatorToken, {
            seed_tracks: seedTrackUris.length ? seedTrackUris : undefined,
            seed_artists: seedArtistIds.length ? seedArtistIds : undefined,
            seed_genres: finalGenres,
        }, targets, limit);
        // Optionally remove already listened tracks for both users (recently played)
        let finalUris = recommendedUris;
        if (!includeKnown) {
            const recents1 = db.db.prepare('SELECT track_json FROM recently_played WHERE user_id=? ORDER BY played_at DESC LIMIT 100').all(creatorId);
            const recents2 = db.db.prepare('SELECT track_json FROM recently_played WHERE user_id=? ORDER BY played_at DESC LIMIT 100').all(partnerId);
            const recentUris = new Set([...recents1, ...recents2]
                .map((r) => JSON.parse(r.track_json))
                .map((t) => t.uri || (t.id ? `spotify:track:${t.id}` : null))
                .filter((u) => !!u));
            finalUris = recommendedUris.filter((u) => !recentUris.has(u));
        }
        // Generate unique playlist name if not provided
        const playlistName = name || generateUniquePlaylistName();
        const playlistDesc = description || 'An AI-blended mix with fresh recommendations';
        // Always create for the creator
        console.log(`[MIXED PLAYLIST] Creating Spotify playlist for creator: "${playlistName}"`);
        const creatorProfile = db.db.prepare('SELECT id FROM users WHERE id=?').get(creatorId);
        const { id: creatorPlaylistId, url: creatorUrl, imageUrl: creatorImageUrl } = await createSpotifyPlaylist(creatorToken, creatorProfile.id, playlistName, playlistDesc);
        console.log(`[MIXED PLAYLIST] Adding ${finalUris.length} tracks to creator playlist ${creatorPlaylistId}`);
        await addTracks(creatorToken, creatorPlaylistId, finalUris);
        console.log(`[MIXED PLAYLIST] Successfully added tracks to creator playlist`);
        let partnerResult = {};
        if (createForBoth) {
            console.log(`[MIXED PLAYLIST] Creating playlist for partner as well: ${partnerId}`);
            try {
                const partnerToken = await ensureValidAccessToken(partnerId);
                const partnerProfile = db.db.prepare('SELECT id FROM users WHERE id=?').get(partnerId);
                if (!partnerProfile) {
                    throw new Error('Partner user not found');
                }
                console.log(`[MIXED PLAYLIST] Creating Spotify playlist for partner: "${playlistName}"`);
                const partnerPlaylist = await createSpotifyPlaylist(partnerToken, partnerProfile.id, playlistName, playlistDesc);
                partnerResult = partnerPlaylist;
                console.log(`[MIXED PLAYLIST] Adding ${finalUris.length} tracks to partner playlist ${partnerResult.id}`);
                await addTracks(partnerToken, partnerResult.id, finalUris);
                console.log(`[MIXED PLAYLIST] Successfully created partner playlist: ${partnerResult.id}`);
            }
            catch (e) {
                // Partner creation may fail (revoked consent, user not found, etc.); still return creator playlist
                const errorMessage = e?.response?.data?.error?.message || e?.message || 'Unknown error';
                console.error('[MIXED PLAYLIST] Partner playlist creation failed:', errorMessage);
                partnerResult.error = errorMessage;
            }
        }
        // Save playlist to database
        const playlistId = uuidv4();
        const now = Date.now();
        console.log('[MIXED PLAYLIST] Saving playlist to database:', {
            id: playlistId,
            name: playlistName,
            trackCount: finalUris.length,
            creatorPlaylistId,
            partnerPlaylistId: partnerResult.id,
            imageUrl: creatorImageUrl,
            trackUris: finalUris.slice(0, 3) // Log first 3 URIs for debugging
        });
        db.db.prepare(`
      INSERT INTO mixed_playlists (
        id, creator_id, partner_id, name, description, vibe, genres, 
        track_uris, creator_spotify_id, partner_spotify_id, 
        creator_spotify_url, partner_spotify_url, creator_spotify_image_url, partner_spotify_image_url,
        created_at, updated_at
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(playlistId, creatorId, partnerId, playlistName, playlistDesc, vibe || null, JSON.stringify(genres || []), JSON.stringify(finalUris), creatorPlaylistId, partnerResult.id || null, creatorUrl, partnerResult.url || null, creatorImageUrl || null, partnerResult.imageUrl || null, now, now);
        const response = {
            id: playlistId,
            name: playlistName,
            description: playlistDesc,
            trackUris: finalUris,
            spotifyImageUrl: creatorImageUrl,
            createdFor: {
                creator: { playlistId: creatorPlaylistId, url: creatorUrl },
                partner: partnerResult.id ? { playlistId: partnerResult.id, url: partnerResult.url } : null,
                partnerError: partnerResult.error || null,
            },
            added: finalUris.length,
        };
        console.log('[MIXED PLAYLIST] Playlist creation completed successfully:', {
            id: playlistId,
            name: playlistName,
            creatorPlaylistId,
            partnerPlaylistId: partnerResult.id,
            trackCount: finalUris.length,
            imageUrl: creatorImageUrl
        });
        res.json(response);
    }
    catch (err) {
        const detail = err?.response?.data || err?.message || 'Unknown error';
        console.error('[MIXED PLAYLIST] Error during playlist creation:', detail);
        console.error('[MIXED PLAYLIST] Full error object:', err);
        res.status(500).json({ error: 'Failed to create mixed playlist', detail });
    }
});
