import { FastifyInstance } from 'fastify';
import { prisma } from '../../../config/database';
import { optionalAuth, requireAdminRole } from '../middleware/auth';
import { logger } from '../../../utils/logger';
import { Prisma } from '@prisma/client';

interface ShortsQuery {
  limit?: string;
  offset?: string;
  sort?: 'recent' | 'popular' | 'random';
}

export async function shortsRoutes(fastify: FastifyInstance) {
  /**
   * GET /api/shorts - Public shorts feed
   * Returns published short videos (<=60s) for the TikTok-style feed
   */
  fastify.get<{ Querystring: ShortsQuery }>(
    '/shorts',
    {
      preHandler: optionalAuth,
    },
    async (request, reply) => {
      const limit = Math.min(parseInt(request.query.limit || '20'), 50);
      const offset = parseInt(request.query.offset || '0');
      const sort = request.query.sort || 'recent';

      const where: Prisma.VideoWhereInput = {
        isShort: true,
        isPublished: true,
        isLocked: false,
      };

      // For random sort, use raw query
      if (sort === 'random') {
        const total = await prisma.video.count({ where });

        const shorts = await prisma.$queryRaw<any[]>`
          SELECT id, title, filename, duration_seconds as "durationSeconds",
                 quality, orientation, thumbnail_path as "thumbnailPath",
                 view_count as "viewCount", upvote_count as "upvoteCount",
                 comment_count as "commentCount", is_locked as "isLocked",
                 width, height, published_at as "publishedAt",
                 category, created_at as "createdAt"
          FROM videos
          WHERE is_short = true AND is_published = true AND is_locked = false
          ORDER BY RANDOM()
          LIMIT ${limit} OFFSET ${offset}
        `;

        const shortsWithUrls = shorts.map((video: any) => ({
          ...video,
          duration: video.durationSeconds,
          thumbnailUrl: video.thumbnailPath ? `/public/${video.id}/thumbnail` : null,
          videoUrl: `/public/${video.id}/stream`,
        }));

        return {
          shorts: shortsWithUrls,
          pagination: {
            total,
            limit,
            offset,
            hasMore: offset + limit < total,
          },
        };
      }

      // Standard Prisma query for recent/popular
      let orderBy: Prisma.VideoOrderByWithRelationInput;
      if (sort === 'popular') {
        orderBy = { viewCount: 'desc' };
      } else {
        orderBy = { publishedAt: 'desc' };
      }

      const [shorts, total] = await Promise.all([
        prisma.video.findMany({
          where,
          select: {
            id: true,
            title: true,
            filename: true,
            durationSeconds: true,
            quality: true,
            orientation: true,
            thumbnailPath: true,
            viewCount: true,
            upvoteCount: true,
            commentCount: true,
            isLocked: true,
            width: true,
            height: true,
            publishedAt: true,
            category: true,
            createdAt: true,
          },
          orderBy,
          take: limit,
          skip: offset,
        }),
        prisma.video.count({ where }),
      ]);

      const shortsWithUrls = shorts.map((video) => ({
        ...video,
        duration: video.durationSeconds,
        thumbnailUrl: video.thumbnailPath ? `/public/${video.id}/thumbnail` : null,
        videoUrl: `/public/${video.id}/stream`,
      }));

      return {
        shorts: shortsWithUrls,
        pagination: {
          total,
          limit,
          offset,
          hasMore: offset + limit < total,
        },
      };
    }
  );

  /**
   * POST /api/shorts/scan - Admin: auto-classify shorts by duration
   * Sets isShort=true for videos <=60s, isShort=false for >60s or null duration
   */
  fastify.post(
    '/shorts/scan',
    {
      preHandler: requireAdminRole,
    },
    async (request, reply) => {
      try {
        const [classified, declassified] = await Promise.all([
          // Mark videos <=60s as shorts
          prisma.video.updateMany({
            where: {
              durationSeconds: { not: null, lte: 60 },
              isShort: false,
            },
            data: { isShort: true },
          }),
          // Unmark videos >60s or with null duration
          prisma.video.updateMany({
            where: {
              OR: [
                { durationSeconds: { gt: 60 } },
                { durationSeconds: null },
              ],
              isShort: true,
            },
            data: { isShort: false },
          }),
        ]);

        const totalShorts = await prisma.video.count({ where: { isShort: true } });

        logger.info(`Shorts scan complete: classified=${classified.count}, declassified=${declassified.count}, totalShorts=${totalShorts}`);

        return {
          classified: classified.count,
          declassified: declassified.count,
          totalShorts,
        };
      } catch (error) {
        logger.error('Failed to scan shorts', { error });
        return reply.code(500).send({ message: 'Failed to scan shorts' });
      }
    }
  );
}
