/**
 * Mentor Workspace Service
 *
 * Manages mentor-applicant workspace: activation, messaging, file management,
 * and file promotion to official submissions. Operates on MentorAssignment,
 * MentorMessage, MentorFile, MentorFileComment, SubmissionPromotionEvent.
 */

import type { PrismaClient, Prisma } from '@prisma/client'
import { logAudit } from '@/server/utils/audit'

// ─── Types ──────────────────────────────────────────────────────────────────

type WorkspaceResult = { success: boolean; errors?: string[] }

// ─── Workspace Activation ───────────────────────────────────────────────────

/**
 * Activate a mentor workspace for a given assignment.
 */
export async function activateWorkspace(
  mentorAssignmentId: string,
  actorId: string,
  prisma: PrismaClient | any,
): Promise<WorkspaceResult> {
  try {
    const assignment = await prisma.mentorAssignment.findUnique({
      where: { id: mentorAssignmentId },
    })

    if (!assignment) {
      return { success: false, errors: ['Mentor assignment not found'] }
    }

    if (assignment.workspaceEnabled) {
      return { success: false, errors: ['Workspace is already enabled'] }
    }

    await prisma.$transaction(async (tx: any) => {
      await tx.mentorAssignment.update({
        where: { id: mentorAssignmentId },
        data: {
          workspaceEnabled: true,
          workspaceOpenAt: new Date(),
        },
      })

      await tx.decisionAuditLog.create({
        data: {
          eventType: 'mentor_workspace.activated',
          entityType: 'MentorAssignment',
          entityId: mentorAssignmentId,
          actorId,
          detailsJson: {
            projectId: assignment.projectId,
            mentorId: assignment.mentorId,
          },
          snapshotJson: { timestamp: new Date().toISOString(), emittedBy: 'mentor-workspace' },
        },
      })

      await logAudit({
        prisma: tx,
        userId: actorId,
        action: 'WORKSPACE_ACTIVATE',
        entityType: 'MentorAssignment',
        entityId: mentorAssignmentId,
        detailsJson: { projectId: assignment.projectId },
      })
    })

    return { success: true }
  } catch (error) {
    console.error('[MentorWorkspace] activateWorkspace failed:', error)
    return {
      success: false,
      errors: [error instanceof Error ? error.message : 'Unknown error'],
    }
  }
}

// ─── Messaging ──────────────────────────────────────────────────────────────

/**
 * Send a message in a mentor workspace.
 */
export async function sendMessage(
  params: {
    mentorAssignmentId: string
    senderId: string
    message: string
    role: 'MENTOR_ROLE' | 'APPLICANT_ROLE' | 'ADMIN_ROLE'
  },
  prisma: PrismaClient | any,
) {
  const assignment = await prisma.mentorAssignment.findUnique({
    where: { id: params.mentorAssignmentId },
  })

  if (!assignment) {
    throw new Error('Mentor assignment not found')
  }

  if (!assignment.workspaceEnabled) {
    throw new Error('Workspace is not enabled for this assignment')
  }

  return prisma.mentorMessage.create({
    data: {
      mentorAssignmentId: params.mentorAssignmentId,
      projectId: assignment.projectId,
      senderId: params.senderId,
      message: params.message,
      role: params.role,
    },
    include: {
      sender: { select: { id: true, name: true, email: true } },
    },
  })
}

/**
 * Get messages for a workspace.
 */
export async function getMessages(
  mentorAssignmentId: string,
  prisma: PrismaClient | any,
) {
  return prisma.mentorMessage.findMany({
    where: { mentorAssignmentId },
    include: {
      sender: { select: { id: true, name: true, email: true, role: true } },
    },
    orderBy: { createdAt: 'asc' },
  })
}

/**
 * Mark a message as read.
 */
export async function markRead(
  messageId: string,
  prisma: PrismaClient | any,
): Promise<void> {
  await prisma.mentorMessage.update({
    where: { id: messageId },
    data: { isRead: true },
  })
}

// ─── File Management ────────────────────────────────────────────────────────

/**
 * Record a file upload in a workspace.
 */
export async function uploadFile(
  params: {
    mentorAssignmentId: string
    uploadedByUserId: string
    fileName: string
    mimeType: string
    size: number
    bucket: string
    objectKey: string
    description?: string
  },
  prisma: PrismaClient | any,
) {
  const assignment = await prisma.mentorAssignment.findUnique({
    where: { id: params.mentorAssignmentId },
  })

  if (!assignment) {
    throw new Error('Mentor assignment not found')
  }

  if (!assignment.workspaceEnabled) {
    throw new Error('Workspace is not enabled for this assignment')
  }

  return prisma.mentorFile.create({
    data: {
      mentorAssignmentId: params.mentorAssignmentId,
      uploadedByUserId: params.uploadedByUserId,
      fileName: params.fileName,
      mimeType: params.mimeType,
      size: params.size,
      bucket: params.bucket,
      objectKey: params.objectKey,
      description: params.description,
    },
    include: {
      uploadedBy: { select: { id: true, name: true, email: true } },
    },
  })
}

/**
 * Add a comment to a file.
 */
export async function addFileComment(
  params: {
    mentorFileId: string
    authorId: string
    content: string
    parentCommentId?: string
  },
  prisma: PrismaClient | any,
) {
  return prisma.mentorFileComment.create({
    data: {
      mentorFileId: params.mentorFileId,
      authorId: params.authorId,
      content: params.content,
      parentCommentId: params.parentCommentId,
    },
    include: {
      author: { select: { id: true, name: true, email: true } },
    },
  })
}

// ─── File Promotion ─────────────────────────────────────────────────────────

/**
 * Promote a mentor file to an official submission.
 * Creates SubmissionPromotionEvent and marks MentorFile.isPromoted = true.
 */
export async function promoteFile(
  params: {
    mentorFileId: string
    roundId: string
    slotKey: string
    promotedById: string
  },
  prisma: PrismaClient | any,
): Promise<{ success: boolean; errors?: string[] }> {
  try {
    const file = await prisma.mentorFile.findUnique({
      where: { id: params.mentorFileId },
      include: {
        mentorAssignment: { select: { projectId: true } },
      },
    })

    if (!file) {
      return { success: false, errors: ['Mentor file not found'] }
    }

    if (file.isPromoted) {
      return { success: false, errors: ['File is already promoted'] }
    }

    await prisma.$transaction(async (tx: any) => {
      // Mark file as promoted
      await tx.mentorFile.update({
        where: { id: params.mentorFileId },
        data: {
          isPromoted: true,
          promotedAt: new Date(),
          promotedByUserId: params.promotedById,
        },
      })

      // Create promotion event
      await tx.submissionPromotionEvent.create({
        data: {
          projectId: file.mentorAssignment.projectId,
          roundId: params.roundId,
          slotKey: params.slotKey,
          sourceType: 'MENTOR_FILE',
          sourceFileId: params.mentorFileId,
          promotedById: params.promotedById,
        },
      })

      await tx.decisionAuditLog.create({
        data: {
          eventType: 'mentor_file.promoted',
          entityType: 'MentorFile',
          entityId: params.mentorFileId,
          actorId: params.promotedById,
          detailsJson: {
            projectId: file.mentorAssignment.projectId,
            roundId: params.roundId,
            slotKey: params.slotKey,
            fileName: file.fileName,
          },
          snapshotJson: { timestamp: new Date().toISOString(), emittedBy: 'mentor-workspace' },
        },
      })

      await logAudit({
        prisma: tx,
        userId: params.promotedById,
        action: 'MENTOR_FILE_PROMOTE',
        entityType: 'MentorFile',
        entityId: params.mentorFileId,
        detailsJson: {
          projectId: file.mentorAssignment.projectId,
          slotKey: params.slotKey,
        },
      })
    })

    return { success: true }
  } catch (error) {
    console.error('[MentorWorkspace] promoteFile failed:', error)
    return {
      success: false,
      errors: [error instanceof Error ? error.message : 'Unknown error'],
    }
  }
}
