import { Router } from 'express';
import { requireAuth, AuthedRequest } from '../middleware/auth.js';
import { addTracks, createSpotifyPlaylist, ensureValidAccessToken, fetchRecommendations, vibeToTargets } from '../lib/spotify.js';
import { db } from '../lib/db.js';

export const playlistsRouter = Router();

// 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: AuthedRequest, res) => {
  try {
    const creatorId = req.user!.uid;
    const { name, description, vibe, genres, includeKnown = true, partnerId, createForBoth = false, limit = 25 } = req.body || {};

    if (!partnerId) return res.status(400).json({ error: 'partnerId required' });

    // Collect seeds from both users' top tracks
    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: Array<{ id?: string; uri?: string; artists?: Array<{ id?: string }> }> = seedRows1.map((r: any) => JSON.parse(r.track_json));
    const tracks2: Array<{ id?: string; uri?: string; artists?: Array<{ id?: string }> }> = seedRows2.map((r: any) => JSON.parse(r.track_json));
    let seedTrackUris = [...tracks1, ...tracks2]
      .map((t) => t.uri || (t.id ? `spotify:track:${t.id}` : null))
      .filter((u): u is string => !!u);

    // Fallback to artist seeds if track seeds are empty
    let seedArtistIds: string[] = [];
    if (seedTrackUris.length === 0) {
      const artistIds = [...tracks1, ...tracks2]
        .flatMap((t) => t.artists || [])
        .map((a) => a?.id)
        .filter((id): id is string => !!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);
    const recommendedUris = await fetchRecommendations(
      creatorToken,
      {
        seed_tracks: seedTrackUris.length ? seedTrackUris : undefined,
        seed_artists: seedArtistIds.length ? seedArtistIds : undefined,
        seed_genres: Array.isArray(genres) && (genres as string[]).length ? (genres as string[]) : (!seedTrackUris.length && !seedArtistIds.length ? ['pop'] : undefined),
      },
      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<string>([...recents1, ...recents2]
        .map((r: any) => JSON.parse(r.track_json))
        .map((t: any) => t.uri || (t.id ? `spotify:track:${t.id}` : null))
        .filter((u: string | null): u is string => !!u));
      finalUris = recommendedUris.filter((u) => !recentUris.has(u));
    }

    const playlistName = name || 'Our Enhanced Mix';
    const playlistDesc = description || 'An AI-blended mix with fresh recommendations';

    // Always create for the creator
    const creatorProfile = db.db.prepare('SELECT id FROM users WHERE id=?').get(creatorId) as { id: string };
    const { id: creatorPlaylistId, url: creatorUrl } = await createSpotifyPlaylist(creatorToken, creatorProfile.id, playlistName, playlistDesc);
    await addTracks(creatorToken, creatorPlaylistId, finalUris);

    let partnerResult: { id?: string; url?: string } = {};
    if (createForBoth) {
      try {
        const partnerToken = await ensureValidAccessToken(partnerId);
        const partnerProfile = db.db.prepare('SELECT id FROM users WHERE id=?').get(partnerId) as { id: string };
        partnerResult = await createSpotifyPlaylist(partnerToken, partnerProfile.id, playlistName, playlistDesc);
        await addTracks(partnerToken, partnerResult.id!, finalUris);
      } catch (e) {
        // Partner creation may fail (revoked consent); still return creator playlist
        console.error('Partner playlist creation failed:', (e as any)?.response?.data || (e as any)?.message);
      }
    }

    res.json({
      createdFor: {
        creator: { playlistId: creatorPlaylistId, url: creatorUrl },
        partner: partnerResult.id ? { playlistId: partnerResult.id, url: partnerResult.url } : null,
      },
      added: finalUris.length,
    });
  } catch (err: any) {
    const detail = err?.response?.data || err?.message || 'Unknown error';
    console.error('Mixed playlist error:', detail);
    res.status(500).json({ error: 'Failed to create mixed playlist', detail });
  }
});


