import { FastifyInstance } from 'fastify';
import { prisma } from '../../../config/database';
import { requireAdminRole } from '../middleware/auth';

interface PaginationQuery {
  limit?: string;
  offset?: string;
  search?: string;
  sortBy?: string;
  sortOrder?: string;
}

interface PlaylistParams {
  id: string;
}

interface UpdatePlaylistBody {
  name?: string;
  description?: string;
  isPublic?: boolean;
}

interface ReorderBody {
  items: Array<{ playlistId: number; position: number }>;
}

export async function playlistsAdminRoutes(fastify: FastifyInstance) {
  // GET /api/media/playlists - All playlists (admin)
  fastify.get<{ Querystring: PaginationQuery }>(
    '/playlists',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const limit = Math.min(parseInt(request.query.limit || '25'), 100);
      const offset = parseInt(request.query.offset || '0');
      const search = request.query.search;
      const sortBy = request.query.sortBy || 'createdAt';
      const sortOrder = request.query.sortOrder === 'asc' ? 'asc' : 'desc';

      const allowedSortFields = ['name', 'videoCount', 'totalDurationSeconds', 'viewCount', 'createdAt'];
      const sortField = allowedSortFields.includes(sortBy) ? sortBy : 'createdAt';

      const where: any = {};
      if (search) {
        where.name = { contains: search, mode: 'insensitive' };
      }

      const playlists = await prisma.playlist.findMany({
        where,
        select: {
          id: true,
          name: true,
          description: true,
          isPublic: true,
          videoCount: true,
          totalDurationSeconds: true,
          viewCount: true,
          createdAt: true,
          updatedAt: true,
          user: {
            select: { id: true, name: true, email: true },
          },
          featured: {
            select: { id: true, position: true, featuredAt: true },
          },
        },
        orderBy: { [sortField]: sortOrder },
        take: limit,
        skip: offset,
      });

      const total = await prisma.playlist.count({ where });

      return {
        data: playlists.map((p) => ({
          id: p.id,
          name: p.name,
          description: p.description,
          isPublic: p.isPublic,
          videoCount: p.videoCount ?? 0,
          totalDurationSeconds: p.totalDurationSeconds ?? 0,
          viewCount: p.viewCount ?? 0,
          createdAt: p.createdAt,
          updatedAt: p.updatedAt,
          creator: {
            id: p.user.id,
            name: p.user.name,
            email: p.user.email,
          },
          isFeatured: !!p.featured,
          featuredPosition: p.featured?.position ?? null,
          featuredAt: p.featured?.featuredAt ?? null,
        })),
        total,
        limit,
        offset,
      };
    }
  );

  // GET /api/media/playlists/featured - Featured playlists (admin)
  fastify.get(
    '/playlists/featured',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const featured = await prisma.featuredPlaylist.findMany({
        orderBy: { position: 'asc' },
        include: {
          playlist: {
            select: {
              id: true,
              name: true,
              description: true,
              isPublic: true,
              videoCount: true,
              totalDurationSeconds: true,
              viewCount: true,
              user: {
                select: { id: true, name: true, email: true },
              },
            },
          },
          featurer: {
            select: { id: true, name: true, email: true },
          },
        },
      });

      return {
        data: featured.map((f) => ({
          id: f.id,
          playlistId: f.playlistId,
          position: f.position,
          featuredBy: f.featurer
            ? { id: f.featurer.id, name: f.featurer.name, email: f.featurer.email }
            : null,
          featuredAt: f.featuredAt,
          playlist: {
            id: f.playlist.id,
            name: f.playlist.name,
            description: f.playlist.description,
            isPublic: f.playlist.isPublic,
            videoCount: f.playlist.videoCount ?? 0,
            totalDurationSeconds: f.playlist.totalDurationSeconds ?? 0,
            viewCount: f.playlist.viewCount ?? 0,
            creator: {
              id: f.playlist.user.id,
              name: f.playlist.user.name,
              email: f.playlist.user.email,
            },
          },
        })),
      };
    }
  );

  // POST /api/media/playlists/:id/feature - Feature a playlist
  fastify.post<{ Params: PlaylistParams }>(
    '/playlists/:id/feature',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const playlistId = parseInt(request.params.id);
      if (isNaN(playlistId)) {
        return reply.code(400).send({ message: 'Invalid playlist ID' });
      }

      const playlist = await prisma.playlist.findUnique({
        where: { id: playlistId },
        select: { id: true },
      });

      if (!playlist) {
        return reply.code(404).send({ message: 'Playlist not found' });
      }

      // Check if already featured
      const existing = await prisma.featuredPlaylist.findUnique({
        where: { playlistId },
      });

      if (existing) {
        return reply.code(409).send({ message: 'Playlist is already featured' });
      }

      // Get next position
      const maxPos = await prisma.featuredPlaylist.aggregate({
        _max: { position: true },
      });

      const nextPosition = (maxPos._max.position ?? -1) + 1;

      const featured = await prisma.featuredPlaylist.create({
        data: {
          playlistId,
          position: nextPosition,
          featuredBy: request.user!.id,
          featuredAt: new Date(),
        },
      });

      return reply.code(201).send(featured);
    }
  );

  // DELETE /api/media/playlists/:id/feature - Unfeature a playlist
  fastify.delete<{ Params: PlaylistParams }>(
    '/playlists/:id/feature',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const playlistId = parseInt(request.params.id);
      if (isNaN(playlistId)) {
        return reply.code(400).send({ message: 'Invalid playlist ID' });
      }

      const existing = await prisma.featuredPlaylist.findUnique({
        where: { playlistId },
      });

      if (!existing) {
        return reply.code(404).send({ message: 'Playlist is not featured' });
      }

      await prisma.featuredPlaylist.delete({ where: { playlistId } });
      return { success: true };
    }
  );

  // PUT /api/media/playlists/featured/reorder - Reorder featured playlists
  fastify.put<{ Body: ReorderBody }>(
    '/playlists/featured/reorder',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const { items } = request.body;
      if (!items || !Array.isArray(items)) {
        return reply.code(400).send({ message: 'items array is required' });
      }

      await prisma.$transaction(
        items.map((item) =>
          prisma.featuredPlaylist.update({
            where: { playlistId: item.playlistId },
            data: { position: item.position },
          })
        )
      );

      return { success: true };
    }
  );

  // PUT /api/media/playlists/:id - Admin update playlist metadata
  fastify.put<{ Params: PlaylistParams; Body: UpdatePlaylistBody }>(
    '/playlists/:id',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const playlistId = parseInt(request.params.id);
      if (isNaN(playlistId)) {
        return reply.code(400).send({ message: 'Invalid playlist ID' });
      }

      const playlist = await prisma.playlist.findUnique({
        where: { id: playlistId },
        select: { id: true },
      });

      if (!playlist) {
        return reply.code(404).send({ message: 'Playlist not found' });
      }

      const { name, description, isPublic } = request.body || {};
      const data: any = {};
      if (name !== undefined) data.name = name;
      if (description !== undefined) data.description = description;
      if (isPublic !== undefined) data.isPublic = isPublic;

      if (Object.keys(data).length === 0) {
        return reply.code(400).send({ message: 'No fields to update' });
      }

      try {
        const updated = await prisma.playlist.update({
          where: { id: playlistId },
          data,
          select: {
            id: true,
            name: true,
            description: true,
            isPublic: true,
            videoCount: true,
            totalDurationSeconds: true,
            viewCount: true,
            createdAt: true,
            updatedAt: true,
          },
        });
        return updated;
      } catch (error: any) {
        if (error.code === 'P2002') {
          return reply.code(409).send({ message: 'A playlist with this name already exists' });
        }
        throw error;
      }
    }
  );

  // POST /api/media/playlists/:id/duplicate - Duplicate a playlist
  fastify.post<{ Params: PlaylistParams }>(
    '/playlists/:id/duplicate',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const playlistId = parseInt(request.params.id);
      if (isNaN(playlistId)) {
        return reply.code(400).send({ message: 'Invalid playlist ID' });
      }

      const source = await prisma.playlist.findUnique({
        where: { id: playlistId },
        select: {
          name: true,
          description: true,
          videos: {
            select: { mediaId: true, position: true },
            orderBy: { position: 'asc' },
          },
        },
      });

      if (!source) {
        return reply.code(404).send({ message: 'Playlist not found' });
      }

      const copyName = `Copy of ${source.name}`.slice(0, 100);

      const newPlaylist = await prisma.playlist.create({
        data: {
          name: copyName,
          description: source.description,
          isPublic: false,
          userId: request.user!.id,
          videoCount: source.videos.length,
        },
      });

      if (source.videos.length > 0) {
        await prisma.playlistVideo.createMany({
          data: source.videos.map((v) => ({
            playlistId: newPlaylist.id,
            mediaId: v.mediaId,
            position: v.position,
          })),
        });
      }

      return reply.code(201).send({
        id: newPlaylist.id,
        name: newPlaylist.name,
        description: newPlaylist.description,
        isPublic: newPlaylist.isPublic,
        videoCount: source.videos.length,
      });
    }
  );

  // DELETE /api/media/playlists/:id - Admin delete any playlist
  fastify.delete<{ Params: PlaylistParams }>(
    '/playlists/:id',
    { preHandler: requireAdminRole },
    async (request, reply) => {
      const playlistId = parseInt(request.params.id);
      if (isNaN(playlistId)) {
        return reply.code(400).send({ message: 'Invalid playlist ID' });
      }

      const playlist = await prisma.playlist.findUnique({
        where: { id: playlistId },
        select: { id: true },
      });

      if (!playlist) {
        return reply.code(404).send({ message: 'Playlist not found' });
      }

      await prisma.playlist.delete({ where: { id: playlistId } });
      return { success: true };
    }
  );
}
