import { NextResponse } from "next/server"
import { z } from "zod"
import { ConvexHttpClient } from "convex/browser"

import { assertStaffSession } from "@/lib/auth-server"
import type { Id } from "@/convex/_generated/dataModel"
import { api } from "@/convex/_generated/api"

export const runtime = "nodejs"

const schema = z.object({
  machineId: z.string().min(1),
  provider: z.string().optional(),
  identifier: z.string().optional(),
  url: z.string().optional(),
  username: z.string().optional(),
  password: z.string().optional(),
  notes: z.string().optional(),
  entryId: z.string().optional(),
  action: z.enum(["save", "upsert", "clear", "delete", "remove"]).optional(),
})

export async function POST(request: Request) {
  const session = await assertStaffSession()
  if (!session) {
    return NextResponse.json({ error: "Não autorizado" }, { status: 401 })
  }

  let parsed: z.infer<typeof schema>
  try {
    const body = await request.json()
    parsed = schema.parse(body)
  } catch {
    return NextResponse.json({ error: "Payload inválido" }, { status: 400 })
  }

  const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL
  if (!convexUrl) {
    return NextResponse.json({ error: "Convex não configurado" }, { status: 500 })
  }

  const client = new ConvexHttpClient(convexUrl)

  try {
    const tenantId =
      session.user.tenantId ??
      process.env.SYNC_TENANT_ID ??
      process.env.SEED_USER_TENANT ??
      "tenant-atlas"
    const ensured = (await client.mutation(api.users.ensureUser, {
      tenantId,
      email: session.user.email,
      name: session.user.name ?? session.user.email,
      avatarUrl: session.user.avatarUrl ?? undefined,
      role: session.user.role.toUpperCase(),
    })) as { _id?: Id<"users"> } | null

    const actorId = ensured?._id as Id<"users"> | undefined
    if (!actorId) {
      return NextResponse.json(
        { error: "Usuário não encontrado no Convex para executar esta ação." },
        { status: 403 }
      )
    }

    const actionRaw = (parsed.action ?? "save").toLowerCase()
    const normalizedAction =
      actionRaw === "clear"
        ? "clear"
        : actionRaw === "delete" || actionRaw === "remove"
          ? "delete"
          : "upsert"

    const provider = (parsed.provider ?? "").trim()
    const identifier = (parsed.identifier ?? "").trim()
    const notes = (parsed.notes ?? "").trim()

    let normalizedUrl: string | undefined
    if (normalizedAction === "upsert") {
      if (!provider || !identifier) {
        return NextResponse.json({ error: "Informe o provedor e o identificador do acesso remoto." }, { status: 400 })
      }
      const rawUrl = (parsed.url ?? "").trim()
      if (rawUrl.length > 0) {
        const candidate = /^https?:\/\//i.test(rawUrl) ? rawUrl : `https://${rawUrl}`
        try {
          new URL(candidate)
          normalizedUrl = candidate
        } catch {
          return NextResponse.json({ error: "URL inválida. Informe um endereço iniciado com http:// ou https://." }, { status: 422 })
        }
      }
    }

    const mutationArgs: Record<string, unknown> = {
      machineId: parsed.machineId as Id<"machines">,
      actorId,
      action: normalizedAction,
    }

    if (parsed.entryId) {
      mutationArgs.entryId = parsed.entryId
    }

    if (normalizedAction === "clear") {
      mutationArgs.clear = true
    } else {
      if (provider) mutationArgs.provider = provider
      if (identifier) mutationArgs.identifier = identifier
      if (normalizedUrl !== undefined) mutationArgs.url = normalizedUrl
      mutationArgs.username = (parsed.username ?? "").trim()
      mutationArgs.password = (parsed.password ?? "").trim()
      if (notes.length) mutationArgs.notes = notes
    }

    const result = (await (client as unknown as { mutation: (name: string, args: Record<string, unknown>) => Promise<unknown> }).mutation(
      "machines:updateRemoteAccess",
      mutationArgs
    )) as { remoteAccess?: unknown } | null

    return NextResponse.json({ ok: true, remoteAccess: result?.remoteAccess ?? null })
  } catch (error) {
    console.error("[machines.remote-access]", error)
    const detail = error instanceof Error ? error.message : null
    const isOutdatedConvex =
      typeof detail === "string" && detail.includes("extra field `action`")

    if (isOutdatedConvex) {
      return NextResponse.json(
        {
          error: "Backend do Convex desatualizado",
          detail: "Recompile/deploy as funções Convex (ex.: `bun run convex:dev:bun` em desenvolvimento ou `bun x convex deploy`) para aplicar o suporte a múltiplos acessos remotos.",
        },
        { status: 409 }
      )
    }

    return NextResponse.json(
      {
        error: "Falha ao atualizar acesso remoto",
        ...(process.env.NODE_ENV !== "production" && detail ? { detail } : {}),
      },
      { status: 500 }
    )
  }
}
