import { z } from "zod"

import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { createCorsPreflight, jsonWithCors } from "@/server/cors"
import { createConvexClient, ConvexConfigurationError } from "@/server/convex-client"
import { checkRateLimit, RATE_LIMITS, rateLimitHeaders } from "@/server/rate-limit"
import { withRetry } from "@/server/retry"

const getMessagesSchema = z.object({
  machineToken: z.string().min(1),
  ticketId: z.string().min(1),
  since: z.number().optional(),
  limit: z.number().optional(),
})

const postMessageSchema = z
  .object({
    machineToken: z.string().min(1),
    ticketId: z.string().min(1),
    body: z.string().max(4000).optional(),
    attachments: z
      .array(
        z.object({
          storageId: z.string(),
          name: z.string(),
          size: z.number().optional(),
          type: z.string().optional(),
        })
      )
      .optional(),
  })
  .superRefine((value, ctx) => {
    const body = (value.body ?? "").trim()
    const hasAttachments = (value.attachments?.length ?? 0) > 0
    if (body.length === 0 && !hasAttachments) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: "Mensagem vazia",
        path: ["body"],
      })
    }
  })

const CORS_METHODS = "POST, OPTIONS"

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

// POST /api/machines/chat/messages
// action=list: Lista mensagens de um chat
// action=send: Envia nova mensagem
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
  try {
    raw = await request.json()
  } catch {
    return jsonWithCors({ error: "JSON invalido" }, 400, origin, CORS_METHODS)
  }

  const action = raw.action ?? "list"
  const machineToken = raw.machineToken as string | undefined

  // Rate limiting por token de maquina
  if (machineToken) {
    const rateLimit = checkRateLimit(
      `chat-messages:${machineToken}`,
      RATE_LIMITS.CHAT_MESSAGES.maxRequests,
      RATE_LIMITS.CHAT_MESSAGES.windowMs
    )

    if (!rateLimit.allowed) {
      return jsonWithCors(
        { error: "Rate limit exceeded", retryAfterMs: rateLimit.retryAfterMs },
        429,
        origin,
        CORS_METHODS,
        rateLimitHeaders(rateLimit)
      )
    }
  }

  if (action === "list") {
    let payload
    try {
      payload = getMessagesSchema.parse(raw)
    } catch (error) {
      return jsonWithCors(
        { error: "Payload invalido", details: error instanceof Error ? error.message : String(error) },
        400,
        origin,
        CORS_METHODS
      )
    }

    try {
      const result = await client.query(api.liveChat.listMachineMessages, {
        machineToken: payload.machineToken,
        ticketId: payload.ticketId as Id<"tickets">,
        since: payload.since,
        limit: payload.limit,
      })
      return jsonWithCors(result, 200, origin, CORS_METHODS)
    } catch (error) {
      console.error("[machines.chat.messages] Falha ao listar mensagens", error)
      const details = error instanceof Error ? error.message : String(error)
      return jsonWithCors({ error: "Falha ao listar mensagens", details }, 500, origin, CORS_METHODS)
    }
  }

  if (action === "send") {
    let payload
    try {
      payload = postMessageSchema.parse(raw)
    } catch (error) {
      return jsonWithCors(
        { error: "Payload invalido", details: error instanceof Error ? error.message : String(error) },
        400,
        origin,
        CORS_METHODS
      )
    }

    try {
      const body = (payload.body ?? "").trim()
      const attachments =
        payload.attachments && payload.attachments.length > 0 ? payload.attachments : undefined

      // Retry com backoff exponencial para falhas transientes
      const result = await withRetry(
        () =>
          client.mutation(api.liveChat.postMachineMessage, {
            machineToken: payload.machineToken,
            ticketId: payload.ticketId as Id<"tickets">,
            body,
            attachments: attachments as
              | Array<{
                  storageId: Id<"_storage">
                  name: string
                  size?: number
                  type?: string
                }>
              | undefined,
          }),
        { maxRetries: 3, baseDelayMs: 100, maxDelayMs: 2000 }
      )
      return jsonWithCors(result, 200, origin, CORS_METHODS)
    } catch (error) {
      console.error("[machines.chat.messages] Falha ao enviar mensagem", error)
      const details = error instanceof Error ? error.message : String(error)
      return jsonWithCors({ error: "Falha ao enviar mensagem", details }, 500, origin, CORS_METHODS)
    }
  }

  return jsonWithCors({ error: "Acao invalida" }, 400, origin, CORS_METHODS)
}
