import { z } from 'zod'
import { router, adminProcedure } from '../trpc'

export const auditRouter = router({
  /**
   * List audit logs with filtering and pagination
   */
  list: adminProcedure
    .input(
      z.object({
        userId: z.string().optional(),
        action: z.string().optional(),
        entityType: z.string().optional(),
        entityId: z.string().optional(),
        startDate: z.date().optional(),
        endDate: z.date().optional(),
        page: z.number().int().min(1).default(1),
        perPage: z.number().int().min(1).max(100).default(50),
      })
    )
    .query(async ({ ctx, input }) => {
      const { userId, action, entityType, entityId, startDate, endDate, page, perPage } = input
      const skip = (page - 1) * perPage

      const where: Record<string, unknown> = {}

      if (userId) where.userId = userId
      if (action) where.action = action
      if (entityType) where.entityType = entityType
      if (entityId) where.entityId = entityId
      if (startDate || endDate) {
        where.timestamp = {}
        if (startDate) (where.timestamp as Record<string, Date>).gte = startDate
        if (endDate) (where.timestamp as Record<string, Date>).lte = endDate
      }

      const [logs, total] = await Promise.all([
        ctx.prisma.auditLog.findMany({
          where,
          skip,
          take: perPage,
          orderBy: { timestamp: 'desc' },
          include: {
            user: { select: { name: true, email: true } },
          },
        }),
        ctx.prisma.auditLog.count({ where }),
      ])

      return {
        logs,
        total,
        page,
        perPage,
        totalPages: Math.ceil(total / perPage),
      }
    }),

  /**
   * Get audit logs for a specific entity
   */
  getByEntity: adminProcedure
    .input(
      z.object({
        entityType: z.string(),
        entityId: z.string(),
      })
    )
    .query(async ({ ctx, input }) => {
      return ctx.prisma.auditLog.findMany({
        where: {
          entityType: input.entityType,
          entityId: input.entityId,
        },
        orderBy: { timestamp: 'desc' },
        include: {
          user: { select: { name: true, email: true } },
        },
      })
    }),

  /**
   * Get audit logs for a specific user
   */
  getByUser: adminProcedure
    .input(
      z.object({
        userId: z.string(),
        limit: z.number().int().min(1).max(100).default(50),
      })
    )
    .query(async ({ ctx, input }) => {
      return ctx.prisma.auditLog.findMany({
        where: { userId: input.userId },
        orderBy: { timestamp: 'desc' },
        take: input.limit,
      })
    }),

  /**
   * Get recent activity summary
   */
  getRecentActivity: adminProcedure
    .input(z.object({ limit: z.number().int().min(1).max(50).default(20) }))
    .query(async ({ ctx, input }) => {
      return ctx.prisma.auditLog.findMany({
        orderBy: { timestamp: 'desc' },
        take: input.limit,
        include: {
          user: { select: { name: true, email: true } },
        },
      })
    }),

  /**
   * Get action statistics
   */
  getStats: adminProcedure
    .input(
      z.object({
        startDate: z.date().optional(),
        endDate: z.date().optional(),
      })
    )
    .query(async ({ ctx, input }) => {
      const where: Record<string, unknown> = {}

      if (input.startDate || input.endDate) {
        where.timestamp = {}
        if (input.startDate) (where.timestamp as Record<string, Date>).gte = input.startDate
        if (input.endDate) (where.timestamp as Record<string, Date>).lte = input.endDate
      }

      const [byAction, byEntity, byUser] = await Promise.all([
        ctx.prisma.auditLog.groupBy({
          by: ['action'],
          where,
          _count: true,
          orderBy: { _count: { action: 'desc' } },
        }),
        ctx.prisma.auditLog.groupBy({
          by: ['entityType'],
          where,
          _count: true,
          orderBy: { _count: { entityType: 'desc' } },
        }),
        ctx.prisma.auditLog.groupBy({
          by: ['userId'],
          where,
          _count: true,
          orderBy: { _count: { userId: 'desc' } },
          take: 10,
        }),
      ])

      // Get user names for top users
      const userIds = byUser
        .map((u) => u.userId)
        .filter((id): id is string => id !== null)

      const users = await ctx.prisma.user.findMany({
        where: { id: { in: userIds } },
        select: { id: true, name: true, email: true },
      })

      const userMap = new Map(users.map((u) => [u.id, u]))

      return {
        byAction: byAction.map((a) => ({
          action: a.action,
          count: a._count,
        })),
        byEntity: byEntity.map((e) => ({
          entityType: e.entityType,
          count: e._count,
        })),
        byUser: byUser.map((u) => ({
          userId: u.userId,
          user: u.userId ? userMap.get(u.userId) : null,
          count: u._count,
        })),
      }
    }),
})
