import { authenticateApiRequest } from '@/lib/api-auth'
import { prisma } from '@/lib/prisma'
import { z } from 'zod'
import { TASK_STATUS_API_VALUES, taskStatusFromApi, taskStatusToApi } from '@/lib/task-status'
import { propagateStatusUpwards } from '@/lib/tasks-status-update'
import { productAccessFilter } from '@/lib/product-access'

// PBI-74 / T-869: force-dynamic zodat Next geen response-cache hangt aan
// deze route — workspace-store leest hier verse data via ensureTaskLoaded.
export const dynamic = 'force-dynamic'

// PBI-74 / T-870: GET-handler voor ensureTaskLoaded. Levert TaskDetail-shape
// (extends BacklogTask met implementation_plan etc.). Access-control via
// product van de parent-story.
export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const auth = await authenticateApiRequest(request)
  if ('error' in auth) {
    return Response.json({ error: auth.error }, { status: auth.status })
  }

  const { id } = await params

  const task = await prisma.task.findFirst({
    where: {
      id,
      story: { product: productAccessFilter(auth.userId) },
    },
    select: {
      id: true,
      title: true,
      description: true,
      priority: true,
      sort_order: true,
      status: true,
      story_id: true,
      created_at: true,
      implementation_plan: true,
      requires_opus: true,
      verify_only: true,
      verify_required: true,
    },
  })
  if (!task) {
    return Response.json({ error: 'Task niet gevonden' }, { status: 404 })
  }

  return Response.json({
    ...task,
    status: taskStatusToApi(task.status),
    _detail: true,
  })
}

// `review` is a valid TaskStatus in the DB and the kanban-board UI, but the
// sprint task list (components/sprint/task-list.tsx) does not yet render it.
// Reject it here until the sprint UI handles REVIEW so external clients don't
// drive tasks into a state the shared UI can't display.
const PATCHABLE_TASK_STATUS = TASK_STATUS_API_VALUES.filter((s) => s !== 'review')

const VERIFY_REQUIRED_VALUES = ['ALIGNED', 'ALIGNED_OR_PARTIAL', 'ANY'] as const

const patchSchema = z
  .object({
    status: z.enum(PATCHABLE_TASK_STATUS as [string, ...string[]]).optional(),
    implementation_plan: z.string().optional(),
    verify_only: z.boolean().optional(),
    verify_required: z.enum(VERIFY_REQUIRED_VALUES).optional(),
  })
  .refine(
    (data) =>
      data.status !== undefined ||
      data.implementation_plan !== undefined ||
      data.verify_only !== undefined ||
      data.verify_required !== undefined,
    { message: 'Geef minimaal status, implementation_plan, verify_only of verify_required mee' },
  )

export async function PATCH(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const auth = await authenticateApiRequest(request)
  if ('error' in auth) {
    return Response.json({ error: auth.error }, { status: auth.status })
  }
  if (auth.isDemo) {
    return Response.json({ error: 'Niet beschikbaar in demo-modus' }, { status: 403 })
  }

  const { id } = await params

  const task = await prisma.task.findFirst({
    where: { id },
    include: {
      story: {
        include: {
          product: {
            include: {
              members: {
                where: { user_id: auth.userId },
                select: { id: true },
              },
            },
          },
        },
      },
    },
  })
  if (!task) {
    return Response.json({ error: 'Taak niet gevonden' }, { status: 404 })
  }

  const hasAccess =
    task.story.product.user_id === auth.userId ||
    (task.story.product.members?.length ?? 0) > 0
  if (!hasAccess) {
    return Response.json({ error: 'Geen toegang' }, { status: 403 })
  }

  let body: unknown
  try {
    body = await request.json()
  } catch {
    return Response.json({ error: 'Malformed JSON' }, { status: 400 })
  }
  const parsed = patchSchema.safeParse(body)
  if (!parsed.success) {
    return Response.json({ error: parsed.error.flatten() }, { status: 422 })
  }

  let dbStatus: ReturnType<typeof taskStatusFromApi> | undefined
  if (parsed.data.status !== undefined) {
    dbStatus = taskStatusFromApi(parsed.data.status)
    if (dbStatus === null) {
      return Response.json(
        { error: { fieldErrors: { status: ['Onbekende status'] } } },
        { status: 422 },
      )
    }
  }

  // Combine simple field writes (plan, verify_only, verify_required) into one update call
  const simpleData: { implementation_plan?: string; verify_only?: boolean; verify_required?: typeof VERIFY_REQUIRED_VALUES[number] } = {}
  if (parsed.data.implementation_plan !== undefined)
    simpleData.implementation_plan = parsed.data.implementation_plan
  if (parsed.data.verify_only !== undefined)
    simpleData.verify_only = parsed.data.verify_only
  if (parsed.data.verify_required !== undefined)
    simpleData.verify_required = parsed.data.verify_required

  const updated = await prisma.$transaction(async (tx) => {
    const simpleUpdate = Object.keys(simpleData).length > 0
      ? await tx.task.update({
          where: { id },
          data: simpleData,
          select: { id: true, status: true, implementation_plan: true, verify_only: true, verify_required: true },
        })
      : null

    if (dbStatus !== undefined && dbStatus !== null) {
      const result = await propagateStatusUpwards(id, dbStatus, tx)
      return {
        id: result.task.id,
        status: result.task.status,
        implementation_plan: result.task.implementation_plan,
        verify_only: simpleUpdate?.verify_only,
        verify_required: simpleUpdate?.verify_required,
      }
    }

    if (simpleUpdate) return simpleUpdate

    // Should not reach here — patchSchema rejects bodies without recognized fields.
    throw new Error('Geen wijzigingen')
  })

  return Response.json({
    id: updated.id,
    status: taskStatusToApi(updated.status),
    implementation_plan: updated.implementation_plan,
    ...(updated.verify_only !== undefined && { verify_only: updated.verify_only }),
    ...(updated.verify_required !== undefined && { verify_required: updated.verify_required }),
  })
}
