'use server'

import { revalidatePath } from 'next/cache'
import { type ClaudeJobStatus } from '@prisma/client'
import { prisma } from '@/lib/prisma'
import { getSession } from '@/lib/auth'
import { ACTIVE_JOB_STATUSES, jobStatusToApi } from '@/lib/job-status'

type EnqueueResult =
  | { success: true; jobId: string }
  | { error: string; jobId?: string }

type EnqueueAllResult =
  | { success: true; count: number }
  | { error: string }

type CancelResult = { success: true } | { error: string }

type RestartResult = { success: true } | { error: string }
const RESTARTABLE_STATUSES: ClaudeJobStatus[] = ['FAILED', 'CANCELLED', 'SKIPPED']

export type PreviewTask = {
  id: string
  title: string
  status: string
  story_title: string
  pbi_id: string
  pbi_status: string
}

type PreflightResult =
  | { error: string }
  | { tasks: PreviewTask[]; blockerIndex: number | null; blockerReason: 'task-review' | 'pbi-blocked' | null }

/**
 * @deprecated Vervangen door startSprintRunAction in actions/sprint-runs.ts.
 * Per-task starts zijn niet meer toegestaan — een sprint draait nu als geheel.
 * Wordt verwijderd zodra de UI is omgebouwd (F4).
 */
export async function enqueueClaudeJobAction(_taskId: string): Promise<EnqueueResult> {
  return {
    error:
      'Per-task starten is niet meer mogelijk. Gebruik "Start Sprint" voor de hele actieve sprint.',
  }
}

/**
 * @deprecated Vervangen door startSprintRunAction in actions/sprint-runs.ts.
 */
export async function enqueueAllTodoJobsAction(_productId: string): Promise<EnqueueAllResult> {
  return {
    error:
      '"Alle TO_DO als jobs queueen" is vervangen door "Start Sprint". Gebruik startSprintRunAction.',
  }
}

/**
 * @deprecated Vervangen door pre-flight in startSprintRunAction (actions/sprint-runs.ts).
 */
export async function previewEnqueueAllAction(_productId: string): Promise<PreflightResult> {
  return {
    error:
      'Per-product preview is vervangen door de pre-flight check in startSprintRunAction.',
  }
}

/**
 * @deprecated Vervangen door startSprintRunAction in actions/sprint-runs.ts.
 */
export async function enqueueClaudeJobsBatchAction(
  _productId: string,
  _taskIds: string[]
): Promise<EnqueueAllResult> {
  return {
    error:
      'Batch-queue per task is vervangen door "Start Sprint". Gebruik startSprintRunAction.',
  }
}

export async function cancelClaudeJobAction(jobId: string): Promise<CancelResult> {
  const session = await getSession()
  if (!session.userId) return { error: 'Niet ingelogd' }
  if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' }

  if (!jobId) return { error: 'job_id is verplicht' }

  const job = await prisma.claudeJob.findFirst({
    where: { id: jobId, user_id: session.userId },
    select: { id: true, status: true, task_id: true, product_id: true },
  })
  if (!job) return { error: 'Job niet gevonden' }

  if (!ACTIVE_JOB_STATUSES.includes(job.status)) {
    return { error: 'Alleen actieve jobs kunnen geannuleerd worden' }
  }

  await prisma.claudeJob.update({
    where: { id: jobId },
    data: { status: 'CANCELLED', finished_at: new Date() },
  })

  await prisma.$executeRaw`
    SELECT pg_notify('scrum4me_changes', ${JSON.stringify({
      type: 'claude_job_status',
      job_id: jobId,
      task_id: job.task_id,
      user_id: session.userId,
      product_id: job.product_id,
      status: jobStatusToApi('CANCELLED'),
    })}::text)
  `

  revalidatePath(`/products/${job.product_id}/solo`)
  return { success: true }
}

export async function restartClaudeJobAction(jobId: string): Promise<RestartResult> {
  const session = await getSession()
  if (!session.userId) return { error: 'Niet ingelogd' }
  if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' }
  if (!jobId) return { error: 'job_id is verplicht' }

  const job = await prisma.claudeJob.findFirst({
    where: { id: jobId, user_id: session.userId },
    select: { id: true, status: true, kind: true, task_id: true, idea_id: true, sprint_run_id: true, product_id: true },
  })
  if (!job) return { error: 'Job niet gevonden' }
  if (!RESTARTABLE_STATUSES.includes(job.status)) {
    return { error: 'Alleen mislukte, geannuleerde of overgeslagen jobs kunnen opnieuw gestart worden' }
  }

  const updated = await prisma.$transaction(async (tx) => {
    const result = await tx.claudeJob.updateMany({
      where: { id: jobId, status: { in: RESTARTABLE_STATUSES } },
      data: {
        status: 'QUEUED',
        retry_count: { increment: 1 },
        claimed_by_token_id: null,
        claimed_at: null,
        started_at: null,
        finished_at: null,
        pushed_at: null,
        verify_result: null,
        error: null,
        summary: null,
        branch: null,
        head_sha: null,
        lease_until: null,
      },
    })
    if (result.count === 0) return 0
    if (job.kind === 'SPRINT_IMPLEMENTATION') {
      await tx.sprintTaskExecution.updateMany({
        where: { sprint_job_id: jobId },
        data: {
          status: 'PENDING',
          verify_result: null,
          verify_summary: null,
          skip_reason: null,
          head_sha: null,
          started_at: null,
          finished_at: null,
        },
      })
    }
    return result.count
  })
  if (updated === 0) {
    return { error: 'Job-status is gewijzigd; herlaad en probeer opnieuw' }
  }

  await prisma.$executeRaw`
    SELECT pg_notify('scrum4me_changes', ${JSON.stringify({
      type: 'claude_job_status',
      job_id: jobId,
      kind: job.kind,
      task_id: job.task_id,
      idea_id: job.idea_id,
      sprint_run_id: job.sprint_run_id,
      user_id: session.userId,
      product_id: job.product_id,
      status: jobStatusToApi('QUEUED'),
    })}::text)
  `

  revalidatePath('/jobs')
  return { success: true }
}
