<script setup lang="ts">
import { computed, ref } from 'vue'

import {
  listAiChannels,
  listAiKeys,
  listAiModels,
} from '@/api/aigateway'
import AiChannelPanel from '@/components/ai/AiChannelPanel.vue'
import AiKeyPanel from '@/components/ai/AiKeyPanel.vue'
import { useAsync } from '@/composables/useAsync'
import { useToast } from '@/composables/useToast'

const message = useToast()

const keys = useAsync(listAiKeys)
const channels = useAsync(listAiChannels)
const models = useAsync(listAiModels)

const baseUrl = `${window.location.origin}/ai/v1`

const endpoints = [
  { method: 'POST', path: '/chat/completions', note: 'OpenAI · 流式/非流式' },
  { method: 'POST', path: '/responses', note: 'OpenAI Responses · 无状态子集' },
  { method: 'POST', path: '/messages', note: 'Claude · 流式/非流式' },
  { method: 'POST', path: '/embeddings', note: 'OpenAI Embeddings · 向量化' },
  { method: 'POST', path: '/audio/speech', note: '文本转语音 · xAI Voice' },
  { method: 'POST', path: '/tts', note: '文本转语音 · xAI 官方格式' },
  { method: 'POST', path: '/rerank', note: '文档重排 · Cohere Rerank' },
  { method: 'POST', path: '/moderations', note: '内容审核 · OCI Guardrails' },
  { method: 'GET', path: '/models', note: '模型列表(按密钥分组过滤)' },
]

/** 厂商显示名:模型名前缀 → 品牌名 */
const VENDOR_LABEL: Record<string, string> = {
  meta: 'Meta', xai: 'xAI', google: 'Google', openai: 'OpenAI', cohere: 'Cohere',
}

/** 可用模型按厂商分组(取模型名前缀,厂商内按名称排序) */
const modelGroups = computed(() => {
  const byVendor = new Map<string, string[]>()
  for (const m of models.data.value ?? []) {
    const vendor = m.id.split('.', 1)[0] || m.owned_by || '其他'
    const list = byVendor.get(vendor) ?? []
    list.push(m.id)
    byVendor.set(vendor, list)
  }
  return [...byVendor.entries()]
    .sort((a, b) => b[1].length - a[1].length)
    .map(([vendor, ids]) => ({ vendor, label: VENDOR_LABEL[vendor] ?? vendor, ids: ids.sort() }))
})

/** 手风琴:同时只展开一个厂商,配合展开区限高控制卡片总高度 */
const expandedVendor = ref<string | null>(null)

function toggleVendor(vendor: string) {
  expandedVendor.value = expandedVendor.value === vendor ? null : vendor
}

/** 渠道现有分组去重,供密钥弹窗快捷选择 */
const groups = computed(() => [...new Set((channels.data.value ?? []).map((c) => c.group).filter(Boolean))])

async function copyBase() {
  try {
    await navigator.clipboard.writeText(baseUrl)
    message.success('已复制 Base URL')
  } catch {
    message.error('复制失败,请手动选择复制')
  }
}

async function copyModel(id: string) {
  try {
    await navigator.clipboard.writeText(id)
    message.success(`已复制:${id}`)
  } catch {
    message.error('复制失败')
  }
}

function refreshChannels() {
  void channels.run({ silent: true })
  void models.run({ silent: true })
}
</script>

<template>
  <div class="flex flex-col gap-4 p-6 pb-8 max-md:p-3">
    <div class="flex flex-wrap items-baseline gap-2.5">
      <h1 class="page-title">AI 网关</h1>
      <span class="text-[13px] text-ink-3">
        把有 Generative AI 配额的租户接入号池,对外提供 OpenAI / Claude 格式的标准接口
      </span>
    </div>

    <div class="grid grid-cols-2 items-start gap-4 max-lg:grid-cols-1">
      <div class="panel">
        <div class="border-b border-line-soft px-4.5 py-3 text-sm font-semibold">接入信息</div>
        <div class="px-4.5 py-2">
          <div class="flex items-center gap-2 border-b border-line-soft py-2 text-[13px]">
            <span class="w-13 flex-none text-[10.5px] font-bold text-ok">BASE</span>
            <span class="mono min-w-0 flex-1 truncate">{{ baseUrl }}</span>
            <NButton size="tiny" quaternary type="primary" @click="copyBase">复制</NButton>
          </div>
          <div
            v-for="ep in endpoints"
            :key="ep.path"
            class="flex items-center gap-2 border-b border-line-soft py-2 text-[13px] last:border-b-0"
          >
            <span class="w-13 flex-none text-[10.5px] font-bold text-ok">{{ ep.method }}</span>
            <span class="mono min-w-0 flex-1">{{ ep.path }}</span>
            <span class="flex-none text-xs text-ink-3">{{ ep.note }}</span>
          </div>
        </div>
        <div class="border-t border-line-soft bg-wash px-4.5 py-2.5 text-xs leading-relaxed text-ink-3">
          鉴权:Authorization: Bearer ‹密钥› 或 x-api-key: ‹密钥› · 两种头都支持,OpenAI / Anthropic SDK 可直接指向 Base URL
        </div>
      </div>

      <div class="panel">
        <div class="flex items-center justify-between border-b border-line-soft px-4.5 py-3">
          <div>
            <div class="text-sm font-semibold">可用模型</div>
            <div class="mt-0.5 text-xs text-ink-3">按厂商分组;点击厂商展开,点击模型名复制</div>
          </div>
          <span class="text-xs text-ink-3">{{ models.data.value?.length ?? '…' }} 个</span>
        </div>
        <div class="px-4.5 py-1.5">
          <div
            v-for="g in modelGroups"
            :key="g.vendor"
            class="border-b border-line-soft py-1 last:border-b-0"
          >
            <button
              type="button"
              class="flex w-full cursor-pointer items-center gap-2 py-1.5 text-left"
              @click="toggleVendor(g.vendor)"
            >
              <svg
                class="h-3 w-3 flex-none text-ink-3 transition-transform"
                :class="expandedVendor === g.vendor ? 'rotate-90' : ''"
                viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"
                stroke-linecap="round" stroke-linejoin="round"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
              <span class="text-[13px] font-medium">{{ g.label }}</span>
              <span class="text-xs text-ink-3">{{ g.ids.length }} 个</span>
            </button>
            <div
              v-if="expandedVendor === g.vendor"
              class="flex max-h-36 flex-wrap content-start gap-1.5 overflow-y-auto pb-2 pl-5"
            >
              <span
                v-for="id in g.ids"
                :key="id"
                class="mono inline-flex items-center overflow-hidden rounded-[5px] border border-line bg-card text-[11.5px]"
              >
                <button
                  type="button"
                  class="cursor-pointer py-0.5 pr-1 pl-2 hover:text-accent"
                  :title="`复制 ${id}`"
                  @click="copyModel(id)"
                >
                  {{ id }}
                </button>
              </span>
            </div>
          </div>
          <div v-if="models.data.value && !models.data.value.length" class="py-2 text-xs text-ink-3">
            暂无可用模型:请先添加渠道并探测(需租户订阅 GenAI 提供区域)
          </div>
        </div>
        <div class="border-t border-line-soft bg-wash px-4.5 py-2.5 text-xs leading-relaxed text-ink-3">
          模型由渠道探测 / 同步自动发现;多模态图片输入视模型而定;Cohere 系工具调用为扁平参数有损降级、不支持图片
        </div>
      </div>
    </div>

    <AiKeyPanel
      :keys="keys.data.value ?? []"
      :loading="keys.loading.value"
      :groups="groups"
      :models="models.data.value ?? []"
      @changed="keys.run({ silent: true })"
    />

    <AiChannelPanel
      :channels="channels.data.value ?? []"
      :loading="channels.loading.value"
      @changed="refreshChannels"
    />
  </div>
</template>
