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

export const exportRouter = router({
  /**
   * Export evaluations as CSV data
   */
  evaluations: adminProcedure
    .input(
      z.object({
        roundId: z.string(),
        includeDetails: z.boolean().default(true),
      })
    )
    .query(async ({ ctx, input }) => {
      const evaluations = await ctx.prisma.evaluation.findMany({
        where: {
          status: 'SUBMITTED',
          assignment: { roundId: input.roundId },
        },
        include: {
          assignment: {
            include: {
              user: { select: { name: true, email: true } },
              project: { select: { title: true, teamName: true, tags: true } },
            },
          },
          form: { select: { criteriaJson: true } },
        },
        orderBy: [
          { assignment: { project: { title: 'asc' } } },
          { submittedAt: 'asc' },
        ],
      })

      // Get criteria labels from form
      const criteriaLabels: Record<string, string> = {}
      if (evaluations.length > 0) {
        const criteria = evaluations[0].form.criteriaJson as Array<{
          id: string
          label: string
        }>
        criteria.forEach((c) => {
          criteriaLabels[c.id] = c.label
        })
      }

      // Build export data
      const data = evaluations.map((e) => {
        const scores = e.criterionScoresJson as Record<string, number> | null
        const criteriaScores: Record<string, number | null> = {}

        Object.keys(criteriaLabels).forEach((id) => {
          criteriaScores[criteriaLabels[id]] = scores?.[id] ?? null
        })

        return {
          projectTitle: e.assignment.project.title,
          teamName: e.assignment.project.teamName,
          tags: e.assignment.project.tags.join(', '),
          jurorName: e.assignment.user.name,
          jurorEmail: e.assignment.user.email,
          ...criteriaScores,
          globalScore: e.globalScore,
          decision: e.binaryDecision ? 'Yes' : 'No',
          feedback: input.includeDetails ? e.feedbackText : null,
          submittedAt: e.submittedAt?.toISOString(),
        }
      })

      // Audit log
      await ctx.prisma.auditLog.create({
        data: {
          userId: ctx.user.id,
          action: 'EXPORT',
          entityType: 'Evaluation',
          detailsJson: { roundId: input.roundId, count: data.length },
          ipAddress: ctx.ip,
          userAgent: ctx.userAgent,
        },
      })

      return {
        data,
        columns: [
          'projectTitle',
          'teamName',
          'tags',
          'jurorName',
          'jurorEmail',
          ...Object.values(criteriaLabels),
          'globalScore',
          'decision',
          ...(input.includeDetails ? ['feedback'] : []),
          'submittedAt',
        ],
      }
    }),

  /**
   * Export project scores summary
   */
  projectScores: adminProcedure
    .input(z.object({ roundId: z.string() }))
    .query(async ({ ctx, input }) => {
      const projects = await ctx.prisma.project.findMany({
        where: { roundId: input.roundId },
        include: {
          assignments: {
            include: {
              evaluation: {
                where: { status: 'SUBMITTED' },
              },
            },
          },
        },
        orderBy: { title: 'asc' },
      })

      const data = projects.map((p) => {
        const evaluations = p.assignments
          .map((a) => a.evaluation)
          .filter((e) => e !== null)

        const globalScores = evaluations
          .map((e) => e?.globalScore)
          .filter((s): s is number => s !== null)

        const yesVotes = evaluations.filter(
          (e) => e?.binaryDecision === true
        ).length

        return {
          title: p.title,
          teamName: p.teamName,
          status: p.status,
          tags: p.tags.join(', '),
          totalEvaluations: evaluations.length,
          averageScore:
            globalScores.length > 0
              ? (
                  globalScores.reduce((a, b) => a + b, 0) / globalScores.length
                ).toFixed(2)
              : null,
          minScore: globalScores.length > 0 ? Math.min(...globalScores) : null,
          maxScore: globalScores.length > 0 ? Math.max(...globalScores) : null,
          yesVotes,
          noVotes: evaluations.length - yesVotes,
          yesPercentage:
            evaluations.length > 0
              ? ((yesVotes / evaluations.length) * 100).toFixed(1)
              : null,
        }
      })

      // Audit log
      await ctx.prisma.auditLog.create({
        data: {
          userId: ctx.user.id,
          action: 'EXPORT',
          entityType: 'ProjectScores',
          detailsJson: { roundId: input.roundId, count: data.length },
          ipAddress: ctx.ip,
          userAgent: ctx.userAgent,
        },
      })

      return {
        data,
        columns: [
          'title',
          'teamName',
          'status',
          'tags',
          'totalEvaluations',
          'averageScore',
          'minScore',
          'maxScore',
          'yesVotes',
          'noVotes',
          'yesPercentage',
        ],
      }
    }),

  /**
   * Export assignments
   */
  assignments: adminProcedure
    .input(z.object({ roundId: z.string() }))
    .query(async ({ ctx, input }) => {
      const assignments = await ctx.prisma.assignment.findMany({
        where: { roundId: input.roundId },
        include: {
          user: { select: { name: true, email: true } },
          project: { select: { title: true, teamName: true } },
          evaluation: { select: { status: true, submittedAt: true } },
        },
        orderBy: [{ project: { title: 'asc' } }, { user: { name: 'asc' } }],
      })

      const data = assignments.map((a) => ({
        projectTitle: a.project.title,
        teamName: a.project.teamName,
        jurorName: a.user.name,
        jurorEmail: a.user.email,
        method: a.method,
        isRequired: a.isRequired ? 'Yes' : 'No',
        isCompleted: a.isCompleted ? 'Yes' : 'No',
        evaluationStatus: a.evaluation?.status ?? 'NOT_STARTED',
        submittedAt: a.evaluation?.submittedAt?.toISOString() ?? null,
        assignedAt: a.createdAt.toISOString(),
      }))

      return {
        data,
        columns: [
          'projectTitle',
          'teamName',
          'jurorName',
          'jurorEmail',
          'method',
          'isRequired',
          'isCompleted',
          'evaluationStatus',
          'submittedAt',
          'assignedAt',
        ],
      }
    }),

  /**
   * Export audit logs as CSV data
   */
  auditLogs: adminProcedure
    .input(
      z.object({
        userId: z.string().optional(),
        action: z.string().optional(),
        entityType: z.string().optional(),
        startDate: z.date().optional(),
        endDate: z.date().optional(),
      })
    )
    .query(async ({ ctx, input }) => {
      const { userId, action, entityType, startDate, endDate } = input

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

      if (userId) where.userId = userId
      if (action) where.action = { contains: action, mode: 'insensitive' }
      if (entityType) where.entityType = entityType
      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 = await ctx.prisma.auditLog.findMany({
        where,
        orderBy: { timestamp: 'desc' },
        include: {
          user: { select: { name: true, email: true } },
        },
        take: 10000, // Limit export to 10k records
      })

      const data = logs.map((log) => ({
        timestamp: log.timestamp.toISOString(),
        userName: log.user?.name ?? 'System',
        userEmail: log.user?.email ?? 'N/A',
        action: log.action,
        entityType: log.entityType,
        entityId: log.entityId ?? '',
        ipAddress: log.ipAddress ?? '',
        userAgent: log.userAgent ?? '',
        details: log.detailsJson ? JSON.stringify(log.detailsJson) : '',
      }))

      return {
        data,
        columns: [
          'timestamp',
          'userName',
          'userEmail',
          'action',
          'entityType',
          'entityId',
          'ipAddress',
          'userAgent',
          'details',
        ],
      }
    }),
})
