'use server'

import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
import { revalidatePath } from 'next/cache'
import { createHash, randomBytes } from 'crypto'

const KEY_PREFIX = 'mcp_key_'

function hashKey(rawKey: string): string {
  return createHash('sha256').update(rawKey).digest('hex')
}

export type McpKeyInfo = {
  shortId: string
  name: string
  userId: string
  userName: string
  active: boolean
  createdAt: string
  lastUsedAt: string | null
}

/**
 * List all MCP API keys for the current user.
 */
export async function listMcpKeys(): Promise<McpKeyInfo[]> {
  const session = await auth()
  if (!session?.user?.id) throw new Error('Unauthorized')

  const allKeys = await prisma.systemConfig.findMany({
    where: { key: { startsWith: KEY_PREFIX } },
  })

  const keys: McpKeyInfo[] = []
  for (const entry of allKeys) {
    try {
      const info = JSON.parse(entry.value)
      if (info.userId !== session.user.id) continue
      keys.push({
        shortId: info.shortId,
        name: info.name,
        userId: info.userId,
        userName: info.userName,
        active: info.active,
        createdAt: info.createdAt,
        lastUsedAt: info.lastUsedAt,
      })
    } catch {
      // skip invalid JSON
    }
  }

  return keys
}

/**
 * Generate a new MCP API key for the current user.
 * Returns the raw key (shown only once) and key info.
 */
export async function generateMcpKey(name: string): Promise<{ rawKey: string; info: { shortId: string; name: string } }> {
  const session = await auth()
  if (!session?.user?.id) throw new Error('Unauthorized')

  const user = await prisma.user.findUnique({
    where: { id: session.user.id },
    select: { id: true, name: true, email: true },
  })
  if (!user) throw new Error('User not found')

  const rawBytes = randomBytes(24)
  const shortId = rawBytes.toString('hex').substring(0, 8)
  const rawKey = `mcp_sk_${rawBytes.toString('hex')}`
  const keyHash = hashKey(rawKey)

  const keyInfo = {
    shortId,
    name: name || `Key for ${user.name}`,
    userId: user.id,
    userName: user.name,
    userEmail: user.email,
    keyHash,
    createdAt: new Date().toISOString(),
    lastUsedAt: null,
    active: true,
  }

  await prisma.systemConfig.create({
    data: {
      key: `${KEY_PREFIX}${shortId}`,
      value: JSON.stringify(keyInfo),
    },
  })

  revalidatePath('/settings/mcp')

  return {
    rawKey,
    info: { shortId, name: keyInfo.name },
  }
}

/**
 * Revoke (deactivate) an MCP API key. Only the owner can revoke.
 */
export async function revokeMcpKey(shortId: string): Promise<boolean> {
  const session = await auth()
  if (!session?.user?.id) throw new Error('Unauthorized')

  const configKey = `${KEY_PREFIX}${shortId}`
  const entry = await prisma.systemConfig.findUnique({ where: { key: configKey } })
  if (!entry) throw new Error('Key not found')

  const info = JSON.parse(entry.value)
  if (info.userId !== session.user.id) throw new Error('Forbidden')
  if (!info.active) return false

  info.active = false
  info.revokedAt = new Date().toISOString()

  await prisma.systemConfig.update({
    where: { key: configKey },
    data: { value: JSON.stringify(info) },
  })

  revalidatePath('/settings/mcp')
  return true
}

/**
 * Permanently delete an MCP API key. Only the owner can delete.
 */
export async function deleteMcpKey(shortId: string): Promise<boolean> {
  const session = await auth()
  if (!session?.user?.id) throw new Error('Unauthorized')

  const configKey = `${KEY_PREFIX}${shortId}`
  const entry = await prisma.systemConfig.findUnique({ where: { key: configKey } })
  if (!entry) throw new Error('Key not found')

  const info = JSON.parse(entry.value)
  if (info.userId !== session.user.id) throw new Error('Forbidden')

  try {
    await prisma.systemConfig.delete({ where: { key: configKey } })
    revalidatePath('/settings/mcp')
    return true
  } catch {
    return false
  }
}

export type McpServerStatus = {
  mode: 'stdio' | 'sse' | 'unknown'
  url: string | null
}

/**
 * Get MCP server status — mode and URL.
 */
export async function getMcpServerStatus(): Promise<McpServerStatus> {
  // Check if SSE mode is configured via env
  const mode = process.env.MCP_SERVER_MODE === 'sse' ? 'sse' : 'stdio'
  const url = process.env.MCP_SERVER_URL || null

  return { mode, url }
}
