import { Router } from 'express';
import { db } from '../lib/db.js';
import axios from 'axios';
import { requireAuth, AuthedRequest } from '../middleware/auth.js';
import { syncUserData } from '../lib/sync.js';
import { ensureValidAccessToken } from '../lib/spotify.js';

export const usersRouter = Router();

// Fetch and store user data (recently played, top tracks/artists)
usersRouter.post('/:uid/sync', requireAuth, async (req: AuthedRequest, res) => {
  try {
    const { uid } = req.params;
    if (!req.user || req.user.uid !== uid) return res.status(403).json({ error: 'Forbidden' });
    await syncUserData(uid);
    res.json({ ok: true });
  } catch (err: any) {
    console.error(err.response?.data || err.message);
    res.status(500).json({ error: 'Sync failed' });
  }
});

usersRouter.get('/:uid', (req, res) => {
  const { uid } = req.params;
  const user = db.db.prepare('SELECT id, display_name, email, avatar_url, country, product, created_at, updated_at, last_synced_at FROM users WHERE id = ?').get(uid);
  if (!user) return res.status(404).json({ error: 'Not found' });
  res.json(user);
});

// Simple search by display_name (substring, case-insensitive)
usersRouter.get('/search/q', (req, res) => {
  const q = String(req.query.q || '').trim();
  if (!q) return res.json([]);
  const rows = db.db
    .prepare('SELECT id, display_name, avatar_url FROM users WHERE lower(display_name) LIKE ? LIMIT 20')
    .all(`%${q.toLowerCase()}%`);
  res.json(rows);
});

usersRouter.get('/:uid/recently-played', (req, res) => {
  const { uid } = req.params;
  const rows = db.db.prepare('SELECT id, user_id, played_at, track_json FROM recently_played WHERE user_id = ? ORDER BY played_at DESC LIMIT 50').all(uid);
  res.json(rows.map(r => ({ id: r.id, user_id: r.user_id, played_at: r.played_at, track: JSON.parse(r.track_json) })));
});

usersRouter.get('/:uid/top-tracks', (req, res) => {
  const { uid } = req.params;
  const range = (req.query.time_range as string) || 'short_term';
  const rows = db.db.prepare('SELECT rank, track_json FROM top_tracks WHERE user_id = ? AND time_range = ? ORDER BY rank ASC').all(uid, range);
  res.json(rows.map(r => ({ rank: r.rank, track: JSON.parse(r.track_json) })));
});

usersRouter.get('/:uid/top-artists', (req, res) => {
  const { uid } = req.params;
  const range = (req.query.time_range as string) || 'short_term';
  const rows = db.db.prepare('SELECT rank, artist_json FROM top_artists WHERE user_id = ? AND time_range = ? ORDER BY rank ASC').all(uid, range);
  res.json(rows.map(r => ({ rank: r.rank, artist: JSON.parse(r.artist_json) })));
});

// status: last sync time and next scheduled time (based on 10 min interval)
usersRouter.get('/:uid/status', (req, res) => {
  const { uid } = req.params;
  const row = db.db.prepare('SELECT last_synced_at FROM users WHERE id = ?').get(uid) as { last_synced_at?: number } | undefined;
  const last = row?.last_synced_at || null;
  // Match backend full sync interval (2 minutes)
  const next = last ? last + 2 * 60 * 1000 : null;
  res.json({ lastSyncedAt: last, nextSyncAt: next });
});

// Now playing (with token refresh)
usersRouter.get('/:uid/now-playing', requireAuth, async (req: AuthedRequest, res) => {
  try {
    const { uid } = req.params;
    if (!req.user) return res.status(403).json({ error: 'Forbidden' });
    if (req.user.uid !== uid) {
      // allow if users are partnered
      const paired = db.db.prepare('SELECT 1 FROM friendships WHERE (user1_id=? AND user2_id=?) OR (user1_id=? AND user2_id=?)').get(req.user.uid, uid, uid, req.user.uid);
      if (!paired) return res.status(403).json({ error: 'Forbidden' });
    }
  // Try DB-captured snapshot first (last 60s)
  const recent = db.db.prepare('SELECT played_at, track_json FROM recently_played WHERE user_id=? ORDER BY played_at DESC LIMIT 1').get(uid) as { played_at?: number; track_json?: string } | undefined;
  if (recent?.played_at && Date.now() - recent.played_at < 60_000 && recent?.track_json) {
    try {
      const item = JSON.parse(recent.track_json);
      return res.json({ is_playing: true, item, source: 'db' });
    } catch {}
  }
    const accessToken = await ensureValidAccessToken(uid);
    const resp = await axios.get('https://api.spotify.com/v1/me/player/currently-playing?additional_types=track', {
      headers: { Authorization: `Bearer ${accessToken}` },
      validateStatus: () => true,
    });
    if (resp.status === 204) return res.json({ is_playing: false });
    if (resp.status >= 400) {
      // Return a benign payload rather than 500 to avoid breaking UI when Spotify returns errors
      return res.json({ is_playing: false });
    }
    return res.status(200).json(resp.data);
  } catch (e: any) {
    res.status(200).json({ is_playing: false });
  }
});

// Audio features bulk
usersRouter.get('/:uid/audio-features', requireAuth, async (req: AuthedRequest, res) => {
  try {
    const { uid } = req.params;
    const ids = String(req.query.ids || '').split(',').map(s => s.trim()).filter(Boolean);
    if (!req.user) return res.status(403).json({ error: 'Forbidden' });
    if (req.user.uid !== uid) {
      const paired = db.db.prepare('SELECT 1 FROM friendships WHERE (user1_id=? AND user2_id=?) OR (user1_id=? AND user2_id=?)').get(req.user.uid, uid, uid, req.user.uid);
      if (!paired) return res.status(403).json({ error: 'Forbidden' });
    }
    if (!ids.length) return res.json({ audio_features: [] });
    const accessToken = await ensureValidAccessToken(uid);
    // Some tracks may be local or missing features; handle gracefully
    const resp = await axios.get('https://api.spotify.com/v1/audio-features', {
      headers: { Authorization: `Bearer ${accessToken}` },
      params: { ids: ids.slice(0, 100).join(',') },
    });
    res.json({ audio_features: Array.isArray(resp.data?.audio_features) ? resp.data.audio_features.filter(Boolean) : [] });
  } catch (e: any) {
    res.status(500).json({ error: 'Failed to fetch audio features', detail: e?.response?.data || e?.message });
  }
});


