"use server"

import { z } from "zod"
import { revalidatePath } from "next/cache"
import { createId } from "@paralleldrive/cuid2"

import type { ActionState } from "@/shared/types/action-state"
import {
  requirePermission,
  PermissionDeniedError,
  getAuthContext,
} from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import { encryptAiApiKey, getAiErrorMessage, testAiProviderById, testAiProviderConfig } from "@/shared/lib/ai"

import {
  countDefaultAiProviders,
  createAiProvider,
  deleteAiProvider as deleteAiProviderRecord,
  getAiProviderForUpdate,
  getAiProviderSummaries as fetchAiProviderSummaries,
  getAiProviderSummariesForUser,
  updateAiProvider,
} from "./data-access"
import type { AiProviderSummary, AiProviderVisibility } from "./types"

export type { AiProviderSummary } from "./types"

const ProviderSchema = z.enum(["zhipu", "openai", "gemini", "custom", "ollama"])
const VisibilitySchema = z.enum(["public", "private"])

const AiProviderFormSchema = z.object({
  id: z.string().optional(),
  provider: ProviderSchema,
  baseUrl: z.string().url().optional().or(z.literal("")),
  model: z.string().min(1),
  apiKey: z.string().min(1).optional(),
  isDefault: z.boolean().optional(),
  visibility: VisibilitySchema.optional(),
})

const AiProviderTestSchema = AiProviderFormSchema.extend({
  apiKey: z.string().optional(),
}).superRefine((data, ctx) => {
  // Ollama 本地部署无需 API Key
  if (data.provider === "ollama") return
  if (!data.apiKey?.trim() && !data.id?.trim()) {
    ctx.addIssue({
      code: z.ZodIssueCode.custom,
      path: ["apiKey"],
      message: "API key is required",
    })
  }
})

/** Ollama 默认 baseUrl（OpenAI 兼容端点） */
const OLLAMA_DEFAULT_BASE_URL = "http://localhost:11434/v1"

/** Ollama 本地部署无需 API Key，使用占位符满足 NOT NULL 约束 */
const OLLAMA_PLACEHOLDER_API_KEY = "ollama"

/** 判断是否为不需要 API Key 的本地 Provider */
const isLocalProvider = (provider: string): boolean => provider === "ollama"

/**
 * 校验当前用户身份，返回 { id, isAdmin }
 *
 * - 所有 AI_CHAT 用户均可访问（用于管理自己的 private provider）
 * - isAdmin 标识是否拥有 AI_CONFIGURE 权限（可管理 public provider 与他人 private）
 */
const ensureUser = async (): Promise<{ id: string; isAdmin: boolean }> => {
  const ctx = await requirePermission(Permissions.AI_CHAT)
  return { id: ctx.userId, isAdmin: ctx.permissions.includes(Permissions.AI_CONFIGURE) }
}

const normalizeBaseUrl = (value: string | undefined): string | null => {
  const raw = String(value ?? "").trim()
  if (!raw.length) return null
  const trimmed = raw.replace(/\/+$/, "")
  return trimmed
    .replace(/\/v1\/chat\/completions$/i, "")
    .replace(/\/chat\/completions$/i, "")
}

/**
 * 解析 Provider 的 baseUrl，应用默认值
 *
 * - Ollama：未提供时使用默认本地地址 http://localhost:11434/v1
 * - 其他 Provider：未提供时返回 null（由调用方校验）
 */
const resolveBaseUrl = (
  provider: string,
  raw: string | undefined
): string | null => {
  const normalized = normalizeBaseUrl(raw)
  if (normalized) return normalized
  if (isLocalProvider(provider)) return OLLAMA_DEFAULT_BASE_URL
  return null
}

/**
 * 获取当前用户可见的 AI Provider 列表
 *
 * - 管理员：返回所有 public + private 记录
 * - 普通用户：返回 public + 自己创建的 private 记录
 */
export async function getAiProviderSummaries(): Promise<ActionState<AiProviderSummary[]>> {
  try {
    const user = await ensureUser()
    const data = user.isAdmin
      ? await fetchAiProviderSummaries()
      : await getAiProviderSummariesForUser(user.id)
    return { success: true, data }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    return { success: false, message: "Failed to load AI providers" }
  }
}

export async function upsertAiProviderAction(
  data: z.infer<typeof AiProviderFormSchema>
): Promise<ActionState<string>> {
  try {
    const user = await ensureUser()
    const parsed = AiProviderFormSchema.safeParse(data)
    if (!parsed.success) {
      return { success: false, message: "Invalid form data" }
    }

    const payload = parsed.data
    const baseUrl = resolveBaseUrl(payload.provider, payload.baseUrl)
    if (!isLocalProvider(payload.provider) && !baseUrl) {
      return { success: false, message: "Base URL is required for this provider" }
    }

    // 可见性规则：
    //   - 管理员可创建/更新 public 或 private
    //   - 普通用户只能创建/更新 private
    const requestedVisibility: AiProviderVisibility = payload.visibility ?? "private"
    const visibility: AiProviderVisibility =
      user.isAdmin ? requestedVisibility : "private"

    // Parallelize default-count and existing-provider queries
    const [defaultCount, existing] = await Promise.all([
      countDefaultAiProviders(),
      payload.id ? getAiProviderForUpdate(payload.id, user.id) : Promise.resolve(null),
    ])
    const hasDefault = defaultCount > 0

    if (payload.id) {
      const id = payload.id
      if (!existing) return { success: false, message: "AI provider not found" }

      // Ollama 无需 API Key：未提供时使用占位符（仅新建时）；更新时保留原值
      const nextKey = payload.apiKey?.trim()
      const effectiveKey = nextKey
        ? nextKey
        : isLocalProvider(payload.provider) && !existing.apiKeyEncrypted
          ? OLLAMA_PLACEHOLDER_API_KEY
          : null
      const encrypted = effectiveKey ? encryptAiApiKey(effectiveKey) : existing.apiKeyEncrypted
      const last4 = effectiveKey ? effectiveKey.slice(-4) : existing.apiKeyLast4

      const isNextDefault =
        payload.isDefault === false && existing.isDefault && defaultCount <= 1
          ? true
          : payload.isDefault ?? existing.isDefault

      await updateAiProvider(
        id,
        {
          provider: payload.provider,
          baseUrl,
          model: payload.model,
          apiKeyEncrypted: encrypted,
          apiKeyLast4: last4,
          isDefault: isNextDefault,
          visibility,
          updatedBy: user.id,
        },
        payload.isDefault === true
      )

      revalidatePath("/admin/ai-settings")
      revalidatePath("/settings")
      return { success: true, message: "AI provider updated", data: id }
    }

    // 新建 Provider：Ollama 允许无 API Key（使用占位符）
    const rawApiKey = payload.apiKey?.trim()
    if (!rawApiKey && !isLocalProvider(payload.provider)) {
      return { success: false, message: "API key is required" }
    }
    const effectiveApiKey = rawApiKey ?? OLLAMA_PLACEHOLDER_API_KEY

    const id = createId()
    const encrypted = encryptAiApiKey(effectiveApiKey)
    const last4 = effectiveApiKey.slice(-4)
    const shouldMakeDefault = payload.isDefault ?? !hasDefault

    await createAiProvider(
      {
        id,
        provider: payload.provider,
        baseUrl,
        model: payload.model,
        apiKeyEncrypted: encrypted,
        apiKeyLast4: last4,
        isDefault: shouldMakeDefault,
        visibility,
        createdBy: user.id,
        updatedBy: user.id,
      },
      shouldMakeDefault
    )

    revalidatePath("/admin/ai-settings")
    revalidatePath("/settings")
    return { success: true, message: "AI provider created", data: id }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    console.error("[upsertAiProviderAction] Failed to save AI provider:", error)
    return { success: false, message: "Failed to save AI provider" }
  }
}

export async function testAiProviderAction(
  data: z.infer<typeof AiProviderTestSchema>
): Promise<ActionState<null>> {
  try {
    await ensureUser()
    const parsed = AiProviderTestSchema.safeParse(data)
    if (!parsed.success) {
      return { success: false, message: "Invalid form data" }
    }
    const payload = parsed.data
    const baseUrl = resolveBaseUrl(payload.provider, payload.baseUrl)
    if (!isLocalProvider(payload.provider) && !baseUrl) {
      return { success: false, message: "Base URL is required for this provider" }
    }
    const model = payload.model.trim()
    const apiKey = payload.apiKey?.trim()
    // Ollama 无 API Key 时使用占位符进行测试
    const effectiveApiKey = apiKey ?? (isLocalProvider(payload.provider) ? OLLAMA_PLACEHOLDER_API_KEY : undefined)
    if (effectiveApiKey) {
      await testAiProviderConfig({ apiKey: effectiveApiKey, baseUrl: baseUrl ?? undefined, model })
    } else if (payload.id) {
      await testAiProviderById(payload.id, { baseUrl: baseUrl ?? undefined, model })
    }
    return { success: true, message: "AI connection ok", data: null }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    return { success: false, message: getAiErrorMessage(error) }
  }
}

const DeleteAiProviderSchema = z.object({
  id: z.string().min(1),
})

/**
 * 删除 AI Provider
 *
 * 权限规则：
 *   - 管理员（AI_CONFIGURE）：可删除任意 Provider
 *   - 普通用户（AI_CHAT）：仅可删除自己创建的 Provider
 *
 * 如果删除的是默认 Provider，自动将最新的一条记录设为默认（若存在）。
 */
export async function deleteAiProviderAction(
  input: z.infer<typeof DeleteAiProviderSchema>
): Promise<ActionState<null>> {
  try {
    const user = await ensureUser()
    const parsed = DeleteAiProviderSchema.safeParse(input)
    if (!parsed.success) {
      return { success: false, message: "Invalid provider id" }
    }
    // 管理员不传 userId（可删除任意）；普通用户传 userId 做所有权校验
    await deleteAiProviderRecord(
      parsed.data.id,
      user.isAdmin ? undefined : user.id
    )
    revalidatePath("/admin/ai-settings")
    revalidatePath("/settings")
    return { success: true, message: "AI provider deleted", data: null }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message }
    return { success: false, message: "Failed to delete AI provider" }
  }
}

/**
 * 检查当前用户是否拥有 AI_CONFIGURE 权限（管理员）
 *
 * 供 UI 层决定是否显示 public 可见性选项。
 */
export async function canConfigurePublicAiProvider(): Promise<ActionState<boolean>> {
  try {
    const ctx = await getAuthContext()
    return { success: true, data: ctx.permissions.includes(Permissions.AI_CONFIGURE) }
  } catch (error) {
    if (error instanceof PermissionDeniedError) return { success: false, message: error.message, data: false }
    return { success: false, message: "Failed to check permission", data: false }
  }
}
