import { NextRequest } from 'next/server'
import { prisma } from '@/lib/prisma'
import { auth } from '@/lib/auth'

export const dynamic = 'force-dynamic'

export async function GET(request: NextRequest): Promise<Response> {
  // Require authentication — prevent unauthenticated access to live vote data
  const userSession = await auth()
  if (!userSession?.user) {
    return new Response(JSON.stringify({ error: 'Unauthorized' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  const { searchParams } = new URL(request.url)
  const sessionId = searchParams.get('sessionId')

  if (!sessionId) {
    return new Response(JSON.stringify({ error: 'sessionId is required' }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  // Verify the session exists
  const session = await prisma.liveVotingSession.findUnique({
    where: { id: sessionId },
    select: { id: true, status: true },
  })

  if (!session) {
    return new Response(JSON.stringify({ error: 'Session not found' }), {
      status: 404,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  const encoder = new TextEncoder()

  const stream = new ReadableStream({
    async start(controller) {
      // Track state for change detection
      let lastVoteCount = -1
      let lastAudienceVoteCount = -1
      let lastProjectId: string | null = null
      let lastStatus: string | null = null

      const sendEvent = (event: string, data: unknown) => {
        const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`
        controller.enqueue(encoder.encode(payload))
      }

      // Send initial connection event
      sendEvent('connected', { sessionId, timestamp: new Date().toISOString() })

      const poll = async () => {
        try {
          const currentSession = await prisma.liveVotingSession.findUnique({
            where: { id: sessionId },
            select: {
              status: true,
              currentProjectId: true,
              currentProjectIndex: true,
              votingEndsAt: true,
              allowAudienceVotes: true,
            },
          })

          if (!currentSession) {
            sendEvent('session_status', { status: 'DELETED' })
            controller.close()
            return false
          }

          // Check for status changes
          if (lastStatus !== null && currentSession.status !== lastStatus) {
            sendEvent('session_status', {
              status: currentSession.status,
              timestamp: new Date().toISOString(),
            })
          }
          lastStatus = currentSession.status

          // Check for project changes
          if (
            lastProjectId !== null &&
            currentSession.currentProjectId !== lastProjectId
          ) {
            sendEvent('project_change', {
              projectId: currentSession.currentProjectId,
              projectIndex: currentSession.currentProjectIndex,
              timestamp: new Date().toISOString(),
            })
          }
          lastProjectId = currentSession.currentProjectId

          // Check for vote updates on the current project
          if (currentSession.currentProjectId) {
            // Jury votes
            const juryVoteCount = await prisma.liveVote.count({
              where: {
                sessionId,
                projectId: currentSession.currentProjectId,
                isAudienceVote: false,
              },
            })

            if (lastVoteCount !== -1 && juryVoteCount !== lastVoteCount) {
              const latestVotes = await prisma.liveVote.findMany({
                where: {
                  sessionId,
                  projectId: currentSession.currentProjectId,
                  isAudienceVote: false,
                },
                select: {
                  score: true,
                  isAudienceVote: true,
                  votedAt: true,
                },
                orderBy: { votedAt: 'desc' },
                take: 1,
              })

              const avgScore = await prisma.liveVote.aggregate({
                where: {
                  sessionId,
                  projectId: currentSession.currentProjectId,
                  isAudienceVote: false,
                },
                _avg: { score: true },
                _count: true,
              })

              sendEvent('vote_update', {
                projectId: currentSession.currentProjectId,
                totalVotes: juryVoteCount,
                averageScore: avgScore._avg.score,
                latestVote: latestVotes[0] || null,
                timestamp: new Date().toISOString(),
              })
            }
            lastVoteCount = juryVoteCount

            // Audience votes (separate event)
            if (currentSession.allowAudienceVotes) {
              const audienceVoteCount = await prisma.liveVote.count({
                where: {
                  sessionId,
                  projectId: currentSession.currentProjectId,
                  isAudienceVote: true,
                },
              })

              if (lastAudienceVoteCount !== -1 && audienceVoteCount !== lastAudienceVoteCount) {
                const audienceAvg = await prisma.liveVote.aggregate({
                  where: {
                    sessionId,
                    projectId: currentSession.currentProjectId,
                    isAudienceVote: true,
                  },
                  _avg: { score: true },
                })

                sendEvent('audience_vote', {
                  projectId: currentSession.currentProjectId,
                  audienceVotes: audienceVoteCount,
                  audienceAverage: audienceAvg._avg.score,
                  timestamp: new Date().toISOString(),
                })
              }
              lastAudienceVoteCount = audienceVoteCount
            }
          }

          // Stop polling if session is completed
          if (currentSession.status === 'COMPLETED') {
            sendEvent('session_status', {
              status: 'COMPLETED',
              timestamp: new Date().toISOString(),
            })
            controller.close()
            return false
          }

          return true
        } catch (error) {
          console.error('[SSE] Poll error:', error)
          return true // Keep trying
        }
      }

      // Initial poll to set baseline state
      const shouldContinue = await poll()
      if (!shouldContinue) return

      // Poll every 2 seconds
      const interval = setInterval(async () => {
        const cont = await poll()
        if (!cont) {
          clearInterval(interval)
        }
      }, 2000)

      // Clean up on abort
      request.signal.addEventListener('abort', () => {
        clearInterval(interval)
        try {
          controller.close()
        } catch {
          // Stream may already be closed
        }
      })
    },
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    },
  })
}
