import { useEffect } from 'react'
import { useJobsStore } from '@/stores/jobs-store'
import type { ClaudeJobStatus } from '@prisma/client'

interface JobStatusPayload {
  job_id: string
  kind?: string
  status: string
  task_id?: string | null
  idea_id?: string | null
  sprint_run_id?: string | null
  branch?: string
  pushed_at?: string
  pr_url?: string
  verify_result?: string
  summary?: string
  error?: string
}

export default function useJobsRealtime() {
  const upsertJob = useJobsStore(s => s.upsertJob)

  useEffect(() => {
    let es: EventSource | null = null
    let reconnectTimer: ReturnType<typeof setTimeout> | null = null
    let active = true
    const inFlight = new Set<string>()

    async function fetchAndUpsert(jobId: string) {
      if (inFlight.has(jobId)) return
      inFlight.add(jobId)
      try {
        const res = await fetch(`/api/jobs/${jobId}`)
        if (!res.ok) return
        const job = await res.json()
        if (active) upsertJob(job)
      } catch {
        // netwerk-/parse-fout: stil
      } finally {
        inFlight.delete(jobId)
      }
    }

    function connect() {
      if (!active) return

      es = new EventSource('/api/realtime/jobs')

      es.addEventListener('jobs_initial', (event) => {
        // De server stuurt JobPayload[] (met `job_id`), niet JobWithRelations[].
        // Daarom geen initJobs-overwrite — de SSR-fetch heeft de volledige
        // shape al in de store geplaatst. We reconcileren alleen status/branch
        // van bekende jobs en fetchen onbekende jobs volledig via REST.
        try {
          const payload = JSON.parse(event.data)
          if (!Array.isArray(payload)) return
          const { activeJobs, doneJobs } = useJobsStore.getState()
          for (const p of payload as JobStatusPayload[]) {
            if (!p.job_id) continue
            const known = activeJobs.some(j => j.id === p.job_id) || doneJobs.some(j => j.id === p.job_id)
            if (!known) {
              void fetchAndUpsert(p.job_id)
            } else {
              upsertJob({
                id: p.job_id,
                status: p.status as ClaudeJobStatus,
                branch: p.branch ?? null,
                error: p.error ?? null,
                summary: p.summary ?? null,
              })
            }
          }
        } catch {
          // malformed JSON
        }
      })

      es.addEventListener('message', (event) => {
        try {
          const payload = JSON.parse(event.data) as JobStatusPayload
          if (!payload.job_id) return
          const { activeJobs, doneJobs } = useJobsStore.getState()
          const known = activeJobs.some(j => j.id === payload.job_id) || doneJobs.some(j => j.id === payload.job_id)
          if (!known) {
            void fetchAndUpsert(payload.job_id)
            return
          }
          upsertJob({
            id: payload.job_id,
            status: payload.status as ClaudeJobStatus,
            branch: payload.branch ?? null,
            prUrl: payload.pr_url ?? null,
            error: payload.error ?? null,
            summary: payload.summary ?? null,
          })
        } catch {
          // malformed JSON
        }
      })

      es.onerror = () => {
        es?.close()
        es = null
        if (active) {
          reconnectTimer = setTimeout(connect, 3000)
        }
      }
    }

    connect()

    return () => {
      active = false
      if (reconnectTimer) clearTimeout(reconnectTimer)
      es?.close()
    }
  }, [upsertJob])
}
