import { eq, and, desc } from 'drizzle-orm';
import { db } from '../db';
import { musicFavorites, musicNowPlaying } from '../schema';

export type FavoriteKind = 'track' | 'album' | 'artist';
export type GroupedFavorites = { tracks: string[]; albums: string[]; artists: string[] };

/** All of a user's favorites, grouped by kind, newest first within each group. */
export async function getMusicFavorites(userId: number): Promise<GroupedFavorites> {
  const rows = await db
    .select({ kind: musicFavorites.kind, key: musicFavorites.key })
    .from(musicFavorites)
    .where(eq(musicFavorites.userId, userId))
    .orderBy(desc(musicFavorites.createdAt));
  const grouped: GroupedFavorites = { tracks: [], albums: [], artists: [] };
  for (const r of rows) {
    if (r.kind === 'track') grouped.tracks.push(r.key);
    else if (r.kind === 'album') grouped.albums.push(r.key);
    else if (r.kind === 'artist') grouped.artists.push(r.key);
  }
  return grouped;
}

/** Add a favorite (idempotent — a repeat add is a no-op via the unique constraint). */
export async function addMusicFavorite(userId: number, kind: FavoriteKind, key: string): Promise<void> {
  await db.insert(musicFavorites).values({ userId, kind, key }).onConflictDoNothing();
}

/** Remove a favorite (no-op if it wasn't set). */
export async function removeMusicFavorite(userId: number, kind: FavoriteKind, key: string): Promise<void> {
  await db
    .delete(musicFavorites)
    .where(and(eq(musicFavorites.userId, userId), eq(musicFavorites.kind, kind), eq(musicFavorites.key, key)));
}

export type NowPlaying = {
  homePath: string;
  dir: string;
  title: string;
  artist: string;
  album: string;
  durationSec: number;
  positionSec: number;
  updatedAt: Date;
};

export type NowPlayingInput = {
  homePath: string;
  dir?: string;
  title?: string;
  artist?: string;
  album?: string;
  durationSec?: number;
  positionSec?: number;
};

/** The user's last "currently playing" snapshot, or null if none. */
export async function getNowPlaying(userId: number): Promise<NowPlaying | null> {
  const [row] = await db
    .select({
      homePath: musicNowPlaying.homePath,
      dir: musicNowPlaying.dir,
      title: musicNowPlaying.title,
      artist: musicNowPlaying.artist,
      album: musicNowPlaying.album,
      durationSec: musicNowPlaying.durationSec,
      positionSec: musicNowPlaying.positionSec,
      updatedAt: musicNowPlaying.updatedAt,
    })
    .from(musicNowPlaying)
    .where(eq(musicNowPlaying.userId, userId));
  return row ?? null;
}

/** Upsert the user's "currently playing" snapshot (one row per user). */
export async function setNowPlaying(userId: number, np: NowPlayingInput): Promise<void> {
  const values = {
    userId,
    homePath: np.homePath,
    dir: np.dir ?? '',
    title: np.title ?? '',
    artist: np.artist ?? '',
    album: np.album ?? '',
    durationSec: np.durationSec ?? 0,
    positionSec: np.positionSec ?? 0,
    updatedAt: new Date(),
  };
  await db
    .insert(musicNowPlaying)
    .values(values)
    .onConflictDoUpdate({
      target: musicNowPlaying.userId,
      set: {
        homePath: values.homePath,
        dir: values.dir,
        title: values.title,
        artist: values.artist,
        album: values.album,
        durationSec: values.durationSec,
        positionSec: values.positionSec,
        updatedAt: values.updatedAt,
      },
    });
}

/** Clear the user's "currently playing" (on close/stop). */
export async function clearNowPlaying(userId: number): Promise<void> {
  await db.delete(musicNowPlaying).where(eq(musicNowPlaying.userId, userId));
}
