import { z } from "zod"

import { api } from "@/convex/_generated/api"
import { createCorsPreflight, jsonWithCors } from "@/server/cors"
import { createConvexClient, ConvexConfigurationError } from "@/server/convex-client"

const tokenModeSchema = z.object({
  machineToken: z.string().min(1),
  hostname: z.string().optional(),
  os: z
    .object({
      name: z.string(),
      version: z.string().optional(),
      architecture: z.string().optional(),
    })
    .optional(),
  metrics: z.record(z.string(), z.unknown()).optional(),
  inventory: z.record(z.string(), z.unknown()).optional(),
})

const provisioningModeSchema = z.object({
  provisioningCode: z.string().min(32),
  hostname: z.string().min(1),
  os: z.object({
    name: z.string().min(1),
    version: z.string().optional(),
    architecture: z.string().optional(),
  }),
  macAddresses: z.array(z.string()).default([]),
  serialNumbers: z.array(z.string()).default([]),
  inventory: z.record(z.string(), z.unknown()).optional(),
  metrics: z.record(z.string(), z.unknown()).optional(),
  registeredBy: z.string().optional(),
})

const CORS_METHODS = "POST, OPTIONS"

export async function OPTIONS(request: Request) {
  return createCorsPreflight(request.headers.get("origin"), CORS_METHODS)
}

export async function POST(request: Request) {
  const origin = request.headers.get("origin")

  let client
  try {
    client = createConvexClient()
  } catch (error) {
    if (error instanceof ConvexConfigurationError) {
      return jsonWithCors({ error: error.message }, 500, origin, CORS_METHODS)
    }
    throw error
  }

  let raw: unknown
  try {
    raw = await request.json()
  } catch (error) {
    return jsonWithCors(
      { error: "Payload inválido", details: error instanceof Error ? error.message : String(error) },
      400,
      origin,
      CORS_METHODS
    )
  }

  // Modo A: com token da máquina (usa heartbeat para juntar inventário)
  const tokenParsed = tokenModeSchema.safeParse(raw)
  if (tokenParsed.success) {
    try {
      const result = await client.mutation(api.machines.heartbeat, {
        machineToken: tokenParsed.data.machineToken,
        hostname: tokenParsed.data.hostname,
        os: tokenParsed.data.os,
        metrics: tokenParsed.data.metrics,
        inventory: tokenParsed.data.inventory,
      })
      return jsonWithCors({ ok: true, machineId: result.machineId, expiresAt: result.expiresAt }, 200, origin, CORS_METHODS)
    } catch (error) {
      console.error("[machines.inventory:token] Falha ao atualizar inventário", error)
      const details = error instanceof Error ? error.message : String(error)
      return jsonWithCors({ error: "Falha ao atualizar inventário", details }, 500, origin, CORS_METHODS)
    }
  }

  // Modo B: com segredo de provisionamento (upsert sem token)
  const provParsed = provisioningModeSchema.safeParse(raw)
  if (provParsed.success) {
    try {
      const result = await client.mutation(api.machines.upsertInventory, {
        provisioningCode: provParsed.data.provisioningCode.trim().toLowerCase(),
        hostname: provParsed.data.hostname,
        os: provParsed.data.os,
        macAddresses: provParsed.data.macAddresses,
        serialNumbers: provParsed.data.serialNumbers,
        inventory: provParsed.data.inventory,
      metrics: provParsed.data.metrics,
      registeredBy: provParsed.data.registeredBy ?? "agent:inventory",
      })
      return jsonWithCors({ ok: true, machineId: result.machineId, status: result.status }, 200, origin, CORS_METHODS)
    } catch (error) {
      console.error("[machines.inventory:prov] Falha ao fazer upsert de inventário", error)
      const details = error instanceof Error ? error.message : String(error)
      return jsonWithCors({ error: "Falha ao fazer upsert de inventário", details }, 500, origin, CORS_METHODS)
    }
  }

  return jsonWithCors({ error: "Formato de payload não suportado" }, 400, origin, CORS_METHODS)
}
