import { NextRequest, NextResponse } from "next/server"
import { auth } from "@/lib/auth"
import { prisma } from "@/lib/prisma"
import { sendNewPhotoEmail } from "@/lib/email"
import { logActivity } from "@/lib/activity-log"
import { logger } from "@/lib/logger"
import { writeFile } from "fs/promises"
import { join } from "path"
import { existsSync, mkdirSync } from "fs"
import { createHash } from "crypto"

// Mark this route as dynamic to prevent build-time data collection
export const dynamic = "force-dynamic"

export async function POST(req: NextRequest) {
  try {
    const session = await auth()

    if (!session) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
    }

    const formData = await req.formData()
    const file = formData.get("file") as File | null
    const answerName = formData.get("answerName") as string | null
    const pointsStr = formData.get("points") as string | null
    const maxAttemptsStr = (formData.get("maxAttempts") as string)?.trim() || ""

    if (!answerName) {
      return NextResponse.json(
        { error: "Answer name is required" },
        { status: 400 }
      )
    }

    // Validate points (must be positive integer, default to 1)
    const pointsValue = pointsStr ? Math.max(1, parseInt(pointsStr, 10)) : 1
    const maxAttemptsValue = maxAttemptsStr && parseInt(maxAttemptsStr, 10) > 0 
      ? parseInt(maxAttemptsStr, 10) 
      : null

    let photoUrl: string
    let fileHash: string | null = null

    if (file) {
      // Handle file upload
      if (!file.type.startsWith("image/")) {
        return NextResponse.json(
          { error: "File must be an image" },
          { status: 400 }
        )
      }

      // Check file size (max 10MB)
      if (file.size > 10 * 1024 * 1024) {
        return NextResponse.json(
          { error: "File size must be less than 10MB" },
          { status: 400 }
        )
      }

      const bytes = await file.arrayBuffer()
      const buffer = Buffer.from(bytes)

      // Calculate SHA256 hash for duplicate detection
      fileHash = createHash("sha256").update(buffer).digest("hex")

      // Check for duplicate file
      const existingPhoto = await prisma.photo.findFirst({
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        where: { fileHash } as any,
      })

      if (existingPhoto) {
        return NextResponse.json(
          { error: "This photo has already been uploaded (duplicate file detected)" },
          { status: 409 }
        )
      }

      // Generate unique filename
      const timestamp = Date.now()
      const randomStr = Math.random().toString(36).substring(2, 15)
      // Sanitize extension - only allow alphanumeric characters
      const rawExtension = file.name.split(".").pop() || "jpg"
      const extension = rawExtension.replace(/[^a-zA-Z0-9]/g, "").toLowerCase() || "jpg"
      const filename = `${timestamp}-${randomStr}.${extension}`

      // Ensure uploads directory exists
      const uploadsDir = join(process.cwd(), "public", "uploads")
      if (!existsSync(uploadsDir)) {
        mkdirSync(uploadsDir, { recursive: true })
        // DEBUG level: directory creation is normal operation
        logger.debug("Created uploads directory", { path: uploadsDir })
      }
      console.log(`[UPLOAD] Using uploads directory: ${uploadsDir} (exists: ${existsSync(uploadsDir)})`)

      // Filename is generated server-side (timestamp + random), safe for path.join
      const filepath = join(uploadsDir, filename)
      await writeFile(filepath, buffer)
      
      // Verify file was written successfully
      const { access } = await import("fs/promises")
      try {
        await access(filepath)
        // DEBUG level: file save verification is normal operation
        logger.debug("File saved successfully", { filepath })
      } catch (error) {
        // ERROR level: file write failure is an error condition
        logger.error("File write verification failed", {
          filepath,
          error: error instanceof Error ? error : new Error(String(error)),
        })
        throw new Error("Failed to save file to disk")
      }

      // Set URL to the uploaded file - use API route to ensure it's accessible
      photoUrl = `/api/uploads/${filename}`
    } else {
      // Handle URL upload (fallback)
      const url = formData.get("url") as string | null
      if (!url) {
        return NextResponse.json(
          { error: "Either file or URL is required" },
          { status: 400 }
        )
      }
      photoUrl = url

      // Check for duplicate URL
      const existingPhoto = await prisma.photo.findFirst({
        where: { url: photoUrl },
      })

      if (existingPhoto) {
        return NextResponse.json(
          { error: "This photo URL has already been uploaded (duplicate URL detected)" },
          { status: 409 }
        )
      }
    }

    const photo = await prisma.photo.create({
      data: {
        uploaderId: session.user.id,
        url: photoUrl,
        fileHash,
        answerName: answerName.trim(),
        points: pointsValue,
        maxAttempts: maxAttemptsValue,
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
      } as any,
      include: {
        uploader: {
          select: {
            name: true,
          },
        },
      },
    })

    // Send emails to all other users
    const allUsers = await prisma.user.findMany({
      where: {
        id: { not: session.user.id },
      },
      select: {
        id: true,
        email: true,
        name: true,
      },
    })

    // Send emails asynchronously (don't wait for them)
    Promise.all(
      allUsers.map((user: { id: string; email: string; name: string }) =>
        sendNewPhotoEmail(user.email, user.name, photo.id, photo.uploader.name).catch(
          (err) => {
            logger.error("Failed to send email", {
              email: user.email,
              photoId: photo.id,
              error: err instanceof Error ? err : new Error(String(err)),
            })
          }
        )
      )
    )

    // Log photo upload activity
    logActivity(
      "PHOTO_UPLOAD",
      "/api/photos/upload",
      "POST",
      session.user,
      {
        photoId: photo.id,
        answerName: photo.answerName,
        points: photo.points,
        filename: photoUrl.split("/").pop()
      },
      req
    )

    return NextResponse.json({ photo }, { status: 201 })
  } catch (error) {
    logger.error("Error uploading photo", {
      error: error instanceof Error ? error : new Error(String(error)),
    })
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    )
  }
}
