import { FastifyInstance } from 'fastify';
import { DbService } from '../services/db.service.js';

export default async function libraryRoutes(fastify: FastifyInstance, options: { dbService: DbService }) {
  const { dbService } = options;

  fastify.get('/tracks', async (request, reply) => {
    const query = request.query as any;
    const tracks = await dbService.getTracks({
      limit: query.limit ? parseInt(query.limit) : undefined,
      offset: query.offset ? parseInt(query.offset) : undefined,
      sort_by: query.sort_by,
      order: query.order,
      search: query.search,
    });
    return tracks;
  });

  // Seeds for the Vibe start screen. Static path, so it is matched ahead of
  // /tracks/:trackId.
  fastify.get('/tracks/seeds', async (request) => {
    const query = request.query as any;
    return await dbService.getSeedTracks(query.limit ? parseInt(query.limit) : undefined);
  });

  fastify.get('/artists', async (request) => {
    const query = request.query as any;
    return await dbService.getArtists({
      limit: query.limit ? parseInt(query.limit) : undefined,
      offset: query.offset ? parseInt(query.offset) : undefined,
    });
  });

  fastify.get('/artists/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const artist = await dbService.getArtistsById(id);
    if (!artist) {
      return reply.code(404).send({ error: 'Artist not found' });
    }
    return artist;
  });

  fastify.get('/artists/:id/similar', async (request, reply) => {
    const { id } = request.params as { id: string };
    const artist = await dbService.getArtistsById(id);
    if (!artist) {
      return reply.code(404).send({ error: 'Artist not found' });
    }
    return await dbService.getSimilarArtists(id);
  });

  fastify.get('/albums', async (request) => {
    const query = request.query as any;
    return await dbService.getAlbums({
      limit: query.limit ? parseInt(query.limit) : undefined,
      offset: query.offset ? parseInt(query.offset) : undefined,
    });
  });

  fastify.get('/albums/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const album = await dbService.getAlbumById(id);
    if (!album) {
      return reply.code(404).send({ error: 'Album not found' });
    }
    return album;
  });

  fastify.get('/library/stats', async () => {
    return await dbService.getLibraryStats();
  });

  // Genres
  fastify.get('/genres', async () => {
    return await dbService.getGenres();
  });

  fastify.get('/genres/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const genre = await dbService.getGenreById(id);
    if (!genre) {
      return reply.code(404).send({ error: 'Genre not found' });
    }
    return genre;
  });

  fastify.get('/genres/:id/tracks', async (request, reply) => {
    const { id } = request.params as { id: string };
    const query = request.query as any;
    return await dbService.getTracksByGenre(
      id,
      query.limit ? parseInt(query.limit) : undefined,
      query.offset ? parseInt(query.offset) : undefined
    );
  });

  // Favorites
  fastify.get('/favorites', async (request, reply) => {
    const userId = (request.headers['x-user-id'] as string) || '00000000-0000-0000-0000-000000000000';
    return await dbService.getFavorites(userId);
  });

  fastify.post('/favorites/:trackId', async (request, reply) => {
    const { trackId } = request.params as { trackId: string };
    const userId = (request.headers['x-user-id'] as string) || '00000000-0000-0000-0000-000000000000';
    await dbService.addFavorite(userId, trackId);
    return reply.send({ status: 'added' });
  });

  fastify.delete('/favorites/:trackId', async (request, reply) => {
    const { trackId } = request.params as { trackId: string };
    const userId = (request.headers['x-user-id'] as string) || '00000000-0000-0000-0000-000000000000';
    await dbService.removeFavorite(userId, trackId);
    return reply.send({ status: 'removed' });
  });

  // Dislikes
  fastify.post('/tracks/:trackId/dislike', async (request, reply) => {
    const { trackId } = request.params as { trackId: string };
    const userId = (request.headers['x-user-id'] as string) || '00000000-0000-0000-0000-000000000000';
    await dbService.dislikeTrack(userId, trackId);
    return reply.send({ status: 'disliked' });
  });

  // Artists CRUD
  fastify.post('/artists', async (request, reply) => {
    const artist = await dbService.createArtist(request.body as any);
    return reply.code(201).send(artist);
  });

  fastify.put('/artists/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const artist = await dbService.updateArtist(id, request.body as any);
    return artist;
  });

  fastify.delete('/artists/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    await dbService.deleteArtist(id);
    return reply.send({ status: 'deleted' });
  });

  // Albums CRUD
  fastify.post('/albums', async (request, reply) => {
    const album = await dbService.createAlbum(request.body as any);
    return reply.code(201).send(album);
  });

  fastify.put('/albums/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const album = await dbService.updateAlbum(id, request.body as any);
    return album;
  });

  fastify.delete('/albums/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    await dbService.deleteAlbum(id);
    return reply.send({ status: 'deleted' });
  });

  // Tracks CRUD
  fastify.get('/tracks/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const track = await dbService.getTrackById(id);
    if (!track) {
      return reply.code(404).send({ error: 'Track not found' });
    }
    return track;
  });

  fastify.get('/tracks/:id/lyrics', async (request, reply) => {
    const { id } = request.params as { id: string };
    const lyrics = await dbService.getTrackLyrics(id);
    if (!lyrics) {
      return reply.code(404).send({ error: 'No lyrics found' });
    }
    return lyrics;
  });

  fastify.post('/tracks', async (request, reply) => {
    const track = await dbService.createTrack(request.body as any);
    return reply.code(201).send(track);
  });

  fastify.put('/tracks/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    const track = await dbService.updateTrack(id, request.body as any);
    return track;
  });

  fastify.delete('/tracks/:id', async (request, reply) => {
    const { id } = request.params as { id: string };
    await dbService.deleteTrack(id);
    return reply.send({ status: 'deleted' });
  });
}
