import { z } from "zod"
import { ConvexHttpClient } from "convex/browser"

import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { env } from "@/lib/env"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { ensureMachineAccount } from "@/server/machines-auth"
import { createCorsPreflight, jsonWithCors } from "@/server/cors"

const registerSchema = z
  .object({
    provisioningSecret: z.string().min(1),
    tenantId: z.string().optional(),
    companySlug: z.string().optional(),
    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([]),
    metadata: z.record(z.string(), z.unknown()).optional(),
    registeredBy: z.string().optional(),
  })
  .refine(
    (data) => (data.macAddresses && data.macAddresses.length > 0) || (data.serialNumbers && data.serialNumbers.length > 0),
    { message: "Informe ao menos um MAC address ou número de série" }
  )

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) {
  if (request.method !== "POST") {
    return jsonWithCors({ error: "Método não permitido" }, 405, request.headers.get("origin"), CORS_METHODS)
  }

  const convexUrl = env.NEXT_PUBLIC_CONVEX_URL
  if (!convexUrl) {
    return jsonWithCors({ error: "Convex não configurado" }, 500, request.headers.get("origin"), CORS_METHODS)
  }

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

  const client = new ConvexHttpClient(convexUrl)

  try {
    const registration = await client.mutation(api.machines.register, {
      provisioningSecret: payload.provisioningSecret,
      tenantId: payload.tenantId ?? DEFAULT_TENANT_ID,
      companySlug: payload.companySlug ?? undefined,
      hostname: payload.hostname,
      os: payload.os,
      macAddresses: payload.macAddresses,
      serialNumbers: payload.serialNumbers,
      metadata: payload.metadata,
      registeredBy: payload.registeredBy,
    })

    const account = await ensureMachineAccount({
      machineId: registration.machineId,
      tenantId: registration.tenantId ?? DEFAULT_TENANT_ID,
      hostname: payload.hostname,
      machineToken: registration.machineToken,
    })

    await client.mutation(api.machines.linkAuthAccount, {
      machineId: registration.machineId as Id<"machines">,
      authUserId: account.authUserId,
      authEmail: account.authEmail,
    })

    return jsonWithCors(
      {
        machineId: registration.machineId,
        tenantId: registration.tenantId,
        companyId: registration.companyId,
        companySlug: registration.companySlug,
        machineToken: registration.machineToken,
        machineEmail: account.authEmail,
        expiresAt: registration.expiresAt,
      },
      { status: 201 },
      request.headers.get("origin"),
      CORS_METHODS
    )
  } catch (error) {
    console.error("[machines.register] Falha no provisionamento", error)
    const details = error instanceof Error ? error.message : String(error)
    return jsonWithCors({ error: "Falha ao provisionar máquina", details }, 500, request.headers.get("origin"), CORS_METHODS)
  }
}
