import { NextResponse } from "next/server"
import { createClient } from "@/lib/supabase/server"
import { isAdminUser } from "@/lib/auth/is-admin"
import type { LocationRow } from "@/lib/locations/tree"

type UpdateLocationBody = {
  value?: string
  parentId?: string | null
  isActive?: boolean
}

function locationsTable(client: Awaited<ReturnType<typeof createClient>>) {
  return client.from("locations" as any) as any
}

export async function PATCH(
  request: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params
  const locationId = id?.trim()

  if (!locationId) {
    return NextResponse.json({ error: "El id de la ubicación es obligatorio" }, { status: 400 })
  }

  const body = (await request.json().catch(() => ({}))) as UpdateLocationBody
  const nextValue = typeof body.value === "string" ? body.value.trim() : undefined
  const hasParentField = Object.prototype.hasOwnProperty.call(body, "parentId")
  const nextParentId =
    hasParentField && typeof body.parentId === "string" && body.parentId.trim().length > 0
      ? body.parentId.trim()
      : hasParentField
        ? null
        : undefined
  const nextIsActive = typeof body.isActive === "boolean" ? body.isActive : undefined

  const supabase = await createClient()
  const {
    data: { session },
    error: sessionError,
  } = await supabase.auth.getSession()
  const user = session?.user

  if (sessionError || !user) {
    return NextResponse.json({ error: "No autorizado" }, { status: 401 })
  }
  if (!isAdminUser(user)) {
    return NextResponse.json({ error: "No tienes permisos para editar ubicaciones" }, { status: 403 })
  }

  const { data: current, error: currentError } = await locationsTable(supabase)
    .select("id, parent_id, value, depth, path, is_active")
    .eq("id", locationId)
    .maybeSingle()

  if (currentError) {
    return NextResponse.json({ error: "No se pudo consultar la ubicación" }, { status: 500 })
  }
  if (!current) {
    return NextResponse.json({ error: "Ubicación no encontrada" }, { status: 404 })
  }

  const finalValue = nextValue && nextValue.length > 0 ? nextValue : (current.value as string)
  let finalParentId = current.parent_id as string | null
  if (nextParentId !== undefined) {
    finalParentId = nextParentId
  }

  if (finalParentId === locationId) {
    return NextResponse.json({ error: "Una ubicación no puede ser padre de sí misma" }, { status: 409 })
  }

  let depth = 1
  let path = [finalValue]
  if (finalParentId) {
    const { data: parent, error: parentError } = await locationsTable(supabase)
      .select("id, depth, path")
      .eq("id", finalParentId)
      .maybeSingle()

    if (parentError) {
      return NextResponse.json({ error: "No se pudo consultar la ubicación padre" }, { status: 500 })
    }
    if (!parent) {
      return NextResponse.json({ error: "No se encontró la ubicación padre" }, { status: 404 })
    }

    const parentPath = (parent.path ?? []) as string[]
    if (parentPath.includes(current.value as string) && finalParentId !== current.parent_id) {
      return NextResponse.json({ error: "El movimiento en el árbol de ubicaciones es inválido" }, { status: 409 })
    }

    depth = (typeof parent.depth === "number" ? parent.depth : 0) + 1
    path = [...parentPath, finalValue]
  }

  if (depth > 20) {
    return NextResponse.json({ error: "La profundidad máxima de ubicaciones es de 20 niveles" }, { status: 409 })
  }

  const payload: Record<string, unknown> = {
    value: finalValue,
    parent_id: finalParentId,
    depth,
    path,
  }
  if (nextIsActive !== undefined) {
    payload.is_active = nextIsActive
  }

  const { data: updated, error: updateError } = await locationsTable(supabase)
    .update(payload)
    .eq("id", locationId)
    .select("id, parent_id, value, depth, path, is_active")
    .maybeSingle()

  if (updateError) {
    return NextResponse.json({ error: "No se pudo actualizar la ubicación" }, { status: 500 })
  }

  return NextResponse.json({ ok: true, location: updated as LocationRow })
}

export async function DELETE(
  _request: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const { id } = await params
  const locationId = id?.trim()

  if (!locationId) {
    return NextResponse.json({ error: "El id de la ubicación es obligatorio" }, { status: 400 })
  }

  const supabase = await createClient()
  const {
    data: { session },
    error: sessionError,
  } = await supabase.auth.getSession()
  const user = session?.user

  if (sessionError || !user) {
    return NextResponse.json({ error: "No autorizado" }, { status: 401 })
  }
  if (!isAdminUser(user)) {
    return NextResponse.json({ error: "No tienes permisos para eliminar ubicaciones" }, { status: 403 })
  }

  const { error: deleteError } = await locationsTable(supabase)
    .delete()
    .eq("id", locationId)

  if (deleteError) {
    return NextResponse.json({ error: "No se pudo eliminar la ubicación" }, { status: 500 })
  }

  return NextResponse.json({ ok: true })
}
