import "server-only"

import type { ChatCompletionMessageParam } from "openai/resources/chat/completions"

import { env } from "@/env.mjs"

export type ChatRole = "system" | "user" | "assistant"

export type ChatMessage = {
  role: ChatRole
  content: string
}

export type AiChatRequest = {
  messages: ChatCompletionMessageParam[]
  model: string
  temperature: number
  maxTokens?: number
  thinking?: Record<string, unknown>
  providerId?: string
}

export const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === "object" && v !== null

const isChatMessage = (v: unknown): v is ChatMessage => {
  if (!isRecord(v)) return false
  const role = String(v.role ?? "")
  if (role !== "system" && role !== "user" && role !== "assistant") return false
  const content = String(v.content ?? "")
  return content.trim().length > 0
}

const extractText = (value: unknown): string => {
  if (typeof value === "string") return value.trim()
  if (Array.isArray(value)) {
    const joined = value.map((item) => extractText(item)).filter(Boolean).join("\n")
    return joined.trim()
  }
  if (isRecord(value)) {
    const candidates = ["text", "content", "output_text", "reasoning", "reasoning_content", "thinking"]
    for (const key of candidates) {
      const text = extractText(value[key])
      if (text) return text
    }
  }
  return ""
}

const extractMessageContent = (message: unknown): string => {
  if (!isRecord(message)) return ""
  const direct = extractText(message.content)
  if (direct) return direct
  const candidates = ["reasoning", "reasoning_content", "thinking", "output", "text"]
  for (const key of candidates) {
    const text = extractText(message[key])
    if (text) return text
  }
  for (const value of Object.values(message)) {
    const text = extractText(value)
    if (text) return text
  }
  return ""
}

export const parseAiChatPayload = (body: unknown): AiChatRequest => {
  if (!isRecord(body)) throw new Error("Invalid payload")

  const rawMessages = Array.isArray(body.messages) ? body.messages : []
  const messages = rawMessages
    .filter(isChatMessage)
    .map((m) => ({ role: m.role, content: m.content })) as ChatCompletionMessageParam[]

  if (messages.length === 0) throw new Error("Messages are required")

  const model = String(body.model ?? env.AI_MODEL ?? "gpt-4o-mini").trim()
  const temperatureRaw = Number(body.temperature ?? 0.2)
  const temperature = Number.isFinite(temperatureRaw) ? Math.min(Math.max(temperatureRaw, 0), 2) : 0.2
  const maxTokensRaw = Number(body.max_tokens ?? body.maxTokens ?? 0)
  const maxTokens = Number.isFinite(maxTokensRaw) && maxTokensRaw > 0 ? Math.floor(maxTokensRaw) : undefined
  const thinking = isRecord(body.thinking) ? body.thinking : undefined
  const providerId = typeof body.providerId === "string" ? body.providerId.trim() : undefined

  return {
    messages,
    model,
    temperature,
    maxTokens,
    thinking,
    providerId: providerId && providerId.length > 0 ? providerId : undefined,
  }
}

export { extractMessageContent }
