<template>
  <div class="llm-config-view">
    <a-page-header
      title="LLM 配置"
      sub-title="管理 LLM 提供商、回退链与部门配额"
      class="llm-config-view__header"
    >
      <template #extra>
        <a-button type="primary" @click="openCreateProvider">
          <PlusOutlined /> 新建提供商
        </a-button>
      </template>
    </a-page-header>

    <a-tabs v-model:activeKey="activeTab">
      <!-- Providers -->
      <a-tab-pane key="providers" tab="提供商">
        <a-card>
          <a-table
            :columns="providerColumns"
            :data-source="providers"
            :row-key="(record: ILlmProvider) => record.name"
            :loading="loadingProviders"
            :pagination="false"
            size="middle"
          >
            <template #bodyCell="{ column, record }: { column: TableColumnType<ILlmProvider>; record: ILlmProvider }">
              <template v-if="column.key === 'models'">
                <a-space :size="4" wrap>
                  <a-tag v-for="m in Object.keys(record.models ?? {})" :key="m" color="blue">{{ m }}</a-tag>
                  <span v-if="Object.keys(record.models ?? {}).length === 0">—</span>
                </a-space>
              </template>
              <template v-else-if="column.key === 'api_key'">
                <code>{{ record.api_key || '—' }}</code>
              </template>
              <template v-else-if="column.key === 'actions'">
                <a-space :size="4">
                  <a-button type="link" size="small" @click="openSetApiKey(record)">设置密钥</a-button>
                  <a-button type="link" size="small" @click="openEditProvider(record)">编辑</a-button>
                  <a-popconfirm
                    title="确认删除该提供商？"
                    ok-text="删除"
                    cancel-text="取消"
                    @confirm="handleDeleteProvider(record)"
                  >
                    <a-button type="link" danger size="small">删除</a-button>
                  </a-popconfirm>
                </a-space>
              </template>
            </template>
          </a-table>
        </a-card>
      </a-tab-pane>

      <!-- Fallbacks -->
      <a-tab-pane key="fallbacks" tab="回退链">
        <a-card>
          <a-space direction="vertical" :size="16" style="width: 100%">
            <a-space :size="8" align="center">
              <a-button @click="loadFallbacks" :loading="loadingFallbacks">刷新</a-button>
              <a-button type="primary" @click="openCreateFallback">新建回退链</a-button>
            </a-space>
            <a-table
              :columns="fallbackColumns"
              :data-source="fallbackRows"
              :row-key="(record: IFallbackRow) => record.model"
              :loading="loadingFallbacks"
              :pagination="false"
              size="middle"
            >
              <template #bodyCell="{ column, record }: { column: TableColumnType<IFallbackRow>; record: IFallbackRow }">
                <template v-if="column.key === 'chain'">
                  <a-space :size="4" wrap>
                    <a-tag v-for="(m, i) in record.chain" :key="i">{{ m }}</a-tag>
                    <span v-if="record.chain.length === 0">—</span>
                  </a-space>
                </template>
                <template v-else-if="column.key === 'actions'">
                  <a-space :size="4">
                    <a-button type="link" size="small" @click="openEditFallback(record)">编辑</a-button>
                    <a-popconfirm
                      title="确认删除该回退链？"
                      ok-text="删除"
                      cancel-text="取消"
                      @confirm="handleDeleteFallback(record)"
                    >
                      <a-button type="link" danger size="small">删除</a-button>
                    </a-popconfirm>
                  </a-space>
                </template>
              </template>
            </a-table>
          </a-space>
        </a-card>
      </a-tab-pane>

      <!-- Quotas -->
      <a-tab-pane key="quotas" tab="部门配额">
        <a-card>
          <a-space direction="vertical" :size="16" style="width: 100%">
            <a-form layout="inline">
              <a-form-item label="选择部门">
                <a-select
                  v-model:value="quotaDeptId"
                  placeholder="选择部门"
                  style="width: 240px"
                  :options="deptOptions"
                  @change="loadQuotas"
                />
              </a-form-item>
              <a-form-item>
                <a-button type="primary" :disabled="!quotaDeptId" @click="openCreateQuota">新建配额</a-button>
              </a-form-item>
            </a-form>

            <a-table
              :columns="quotaColumns"
              :data-source="quotas"
              :row-key="(record: IQuota) => record.id"
              :loading="loadingQuotas"
              :pagination="false"
              size="middle"
            >
              <template #bodyCell="{ column, record }: { column: TableColumnType<IQuota>; record: IQuota }">
                <template v-if="column.key === 'limit_value'">
                  <span v-if="Array.isArray(record.limit_value)">
                    <a-tag v-for="(m, i) in record.limit_value" :key="i">{{ m }}</a-tag>
                  </span>
                  <span v-else>{{ record.limit_value }}</span>
                </template>
                <template v-else-if="column.key === 'actions'">
                  <a-popconfirm
                    title="确认删除该配额？"
                    ok-text="删除"
                    cancel-text="取消"
                    @confirm="handleDeleteQuota(record)"
                  >
                    <a-button type="link" danger size="small">删除</a-button>
                  </a-popconfirm>
                </template>
              </template>
            </a-table>
          </a-space>
        </a-card>
      </a-tab-pane>
    </a-tabs>

    <!-- Create / Edit provider modal -->
    <a-modal
      v-model:open="providerFormOpen"
      :title="editingProviderName ? '编辑提供商' : '新建提供商'"
      :confirm-loading="submittingProvider"
      ok-text="保存"
      cancel-text="取消"
      @ok="handleSubmitProvider"
    >
      <a-form layout="vertical">
        <a-form-item label="名称" required>
          <a-input v-model:value="providerForm.name" :disabled="!!editingProviderName" placeholder="提供商名称" />
        </a-form-item>
        <a-form-item label="类型">
          <a-select v-model:value="providerForm.type" :options="providerTypeOptions" />
        </a-form-item>
        <a-form-item v-if="!editingProviderName" label="API Key" required>
          <a-input-password v-model:value="providerForm.api_key" placeholder="输入 API Key" />
        </a-form-item>
        <a-form-item label="Base URL">
          <a-input v-model:value="providerForm.base_url" placeholder="https://api.openai.com/v1（可选）" />
        </a-form-item>
        <a-form-item label="Max Tokens">
          <a-input-number v-model:value="providerForm.max_tokens" :min="1" :max="1000000" style="width: 100%" />
        </a-form-item>
        <a-form-item label="Timeout (秒)">
          <a-input-number v-model:value="providerForm.timeout" :min="1" :max="600" style="width: 100%" />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- Set API key modal -->
    <a-modal
      v-model:open="apiKeyFormOpen"
      title="设置 API Key"
      :confirm-loading="submittingApiKey"
      ok-text="保存"
      cancel-text="取消"
      @ok="handleSubmitApiKey"
    >
      <a-form layout="vertical">
        <a-form-item label="提供商">
          <a-input :value="apiKeyTarget" disabled />
        </a-form-item>
        <a-form-item label="新 API Key" required>
          <a-input-password v-model:value="apiKeyForm.api_key" placeholder="输入新的 API Key" />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- Create / Edit fallback modal -->
    <a-modal
      v-model:open="fallbackFormOpen"
      :title="editingFallbackModel ? '编辑回退链' : '新建回退链'"
      :confirm-loading="submittingFallback"
      ok-text="保存"
      cancel-text="取消"
      @ok="handleSubmitFallback"
    >
      <a-form layout="vertical">
        <a-form-item label="模型名称" required>
          <a-input v-model:value="fallbackForm.model" :disabled="!!editingFallbackModel" placeholder="如 gpt-4" />
        </a-form-item>
        <a-form-item label="回退链（每行一个）" required>
          <a-textarea
            v-model:value="fallbackChainText"
            :rows="5"
            placeholder="provider/model&#10;provider2/model2"
          />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- Create quota modal -->
    <a-modal
      v-model:open="quotaFormOpen"
      title="新建配额"
      :confirm-loading="submittingQuota"
      ok-text="保存"
      cancel-text="取消"
      @ok="handleSubmitQuota"
    >
      <a-form layout="vertical">
        <a-form-item label="配额类型" required>
          <a-select v-model:value="quotaForm.quota_type" :options="quotaTypeOptions" />
        </a-form-item>
        <a-form-item label="周期">
          <a-select v-model:value="quotaForm.period" :options="quotaPeriodOptions" />
        </a-form-item>
        <a-form-item v-if="quotaForm.quota_type !== 'model_whitelist'" label="限制值" required>
          <a-input-number v-model:value="quotaLimitNumber" :min="0" style="width: 100%" />
        </a-form-item>
        <a-form-item v-else label="模型白名单（每行一个）" required>
          <a-textarea v-model:value="quotaWhitelistText" :rows="4" placeholder="gpt-4&#10;claude-3" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
/**
 * LLM configuration view — providers, fallback chains, department quotas.
 */
import { ref, reactive, computed, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import type { TableColumnType } from 'ant-design-vue'
import { PlusOutlined } from '@ant-design/icons-vue'
import { adminApi, type ILlmProvider, type IQuota, type IDepartment } from '@/api/admin'

interface ISelectOption {
  label: string
  value: string
}

interface IFallbackRow {
  model: string
  chain: string[]
}

const activeTab = ref<'providers' | 'fallbacks' | 'quotas'>('providers')

// --- Providers ---
const providers = ref<ILlmProvider[]>([])
const loadingProviders = ref(false)

const providerColumns: TableColumnType<ILlmProvider>[] = [
  { title: '名称', key: 'name', dataIndex: 'name', width: 160 },
  { title: '类型', key: 'type', dataIndex: 'type', width: 120 },
  { title: '模型', key: 'models', width: 280 },
  { title: 'API Key', key: 'api_key', width: 200, ellipsis: true },
  { title: '操作', key: 'actions', width: 220 },
]

const providerTypeOptions: ISelectOption[] = [
  { label: 'openai', value: 'openai' },
  { label: 'anthropic', value: 'anthropic' },
  { label: 'gemini', value: 'gemini' },
  { label: 'doubao', value: 'doubao' },
  { label: 'wenxin', value: 'wenxin' },
  { label: 'yuanbao', value: 'yuanbao' },
]

async function loadProviders(): Promise<void> {
  loadingProviders.value = true
  try {
    providers.value = await adminApi.listLlmProviders()
  } catch (err) {
    message.error(extractMessage(err, '加载提供商列表失败'))
  } finally {
    loadingProviders.value = false
  }
}

// Provider form
const providerFormOpen = ref(false)
const editingProviderName = ref<string | null>(null)
const submittingProvider = ref(false)
const providerForm = reactive({
  name: '',
  type: 'openai',
  api_key: '',
  base_url: '',
  max_tokens: 4096,
  timeout: 60,
})

function openCreateProvider(): void {
  editingProviderName.value = null
  providerForm.name = ''
  providerForm.type = 'openai'
  providerForm.api_key = ''
  providerForm.base_url = ''
  providerForm.max_tokens = 4096
  providerForm.timeout = 60
  providerFormOpen.value = true
}

function openEditProvider(record: ILlmProvider): void {
  editingProviderName.value = record.name
  providerForm.name = record.name
  providerForm.type = record.type
  providerForm.api_key = ''
  providerForm.base_url = record.base_url
  providerForm.max_tokens = record.max_tokens
  providerForm.timeout = record.timeout
  providerFormOpen.value = true
}

async function handleSubmitProvider(): Promise<void> {
  if (!providerForm.name.trim()) {
    message.warning('请输入提供商名称')
    return
  }
  submittingProvider.value = true
  try {
    if (editingProviderName.value) {
      const config: Record<string, unknown> = {
        type: providerForm.type,
        base_url: providerForm.base_url,
        max_tokens: providerForm.max_tokens,
        timeout: providerForm.timeout,
      }
      if (providerForm.api_key) config.api_key = providerForm.api_key
      await adminApi.updateLlmProvider(editingProviderName.value, config)
      message.success('提供商已更新')
    } else {
      if (!providerForm.api_key) {
        message.warning('请输入 API Key')
        submittingProvider.value = false
        return
      }
      await adminApi.createLlmProvider(providerForm.name.trim(), {
        type: providerForm.type,
        api_key: providerForm.api_key,
        base_url: providerForm.base_url,
        max_tokens: providerForm.max_tokens,
        timeout: providerForm.timeout,
      })
      message.success('提供商已创建')
    }
    providerFormOpen.value = false
    await loadProviders()
  } catch (err) {
    message.error(extractMessage(err, '保存提供商失败'))
  } finally {
    submittingProvider.value = false
  }
}

async function handleDeleteProvider(record: ILlmProvider): Promise<void> {
  try {
    await adminApi.deleteLlmProvider(record.name)
    message.success('提供商已删除')
    await loadProviders()
  } catch (err) {
    message.error(extractMessage(err, '删除提供商失败'))
  }
}

// API key modal
const apiKeyFormOpen = ref(false)
const submittingApiKey = ref(false)
const apiKeyTarget = ref('')
const apiKeyForm = reactive({ api_key: '' })

function openSetApiKey(record: ILlmProvider): void {
  apiKeyTarget.value = record.name
  apiKeyForm.api_key = ''
  apiKeyFormOpen.value = true
}

async function handleSubmitApiKey(): Promise<void> {
  if (!apiKeyForm.api_key) {
    message.warning('请输入 API Key')
    return
  }
  submittingApiKey.value = true
  try {
    await adminApi.setLlmApiKey(apiKeyTarget.value, apiKeyForm.api_key)
    message.success('API Key 已更新')
    apiKeyFormOpen.value = false
    await loadProviders()
  } catch (err) {
    message.error(extractMessage(err, '设置 API Key 失败'))
  } finally {
    submittingApiKey.value = false
  }
}

// --- Fallbacks ---
const fallbacks = ref<Record<string, string[]>>({})
const loadingFallbacks = ref(false)

const fallbackRows = computed<IFallbackRow[]>(() =>
  Object.entries(fallbacks.value).map(([model, chain]) => ({ model, chain })),
)

const fallbackColumns: TableColumnType<IFallbackRow>[] = [
  { title: '模型', key: 'model', dataIndex: 'model', width: 200 },
  { title: '回退链', key: 'chain' },
  { title: '操作', key: 'actions', width: 160 },
]

async function loadFallbacks(): Promise<void> {
  loadingFallbacks.value = true
  try {
    fallbacks.value = await adminApi.listLlmFallbacks()
  } catch (err) {
    message.error(extractMessage(err, '加载回退链失败'))
  } finally {
    loadingFallbacks.value = false
  }
}

const fallbackFormOpen = ref(false)
const editingFallbackModel = ref<string | null>(null)
const submittingFallback = ref(false)
const fallbackForm = reactive({ model: '' })
const fallbackChainText = ref('')

function openCreateFallback(): void {
  editingFallbackModel.value = null
  fallbackForm.model = ''
  fallbackChainText.value = ''
  fallbackFormOpen.value = true
}

function openEditFallback(record: IFallbackRow): void {
  editingFallbackModel.value = record.model
  fallbackForm.model = record.model
  fallbackChainText.value = record.chain.join('\n')
  fallbackFormOpen.value = true
}

async function handleSubmitFallback(): Promise<void> {
  if (!fallbackForm.model.trim()) {
    message.warning('请输入模型名称')
    return
  }
  const chain = fallbackChainText.value
    .split('\n')
    .map((s) => s.trim())
    .filter((s) => s.length > 0)
  if (chain.length === 0) {
    message.warning('请输入至少一个回退项')
    return
  }
  submittingFallback.value = true
  try {
    await adminApi.setLlmFallback(fallbackForm.model.trim(), chain)
    message.success('回退链已保存')
    fallbackFormOpen.value = false
    await loadFallbacks()
  } catch (err) {
    message.error(extractMessage(err, '保存回退链失败'))
  } finally {
    submittingFallback.value = false
  }
}

async function handleDeleteFallback(record: IFallbackRow): Promise<void> {
  try {
    await adminApi.deleteLlmFallback(record.model)
    message.success('回退链已删除')
    await loadFallbacks()
  } catch (err) {
    message.error(extractMessage(err, '删除回退链失败'))
  }
}

// --- Quotas ---
const departments = ref<IDepartment[]>([])
const quotaDeptId = ref<string | undefined>(undefined)
const quotas = ref<IQuota[]>([])
const loadingQuotas = ref(false)

const deptOptions = computed<ISelectOption[]>(() =>
  departments.value.map((d) => ({ label: d.name, value: d.id })),
)

const quotaColumns: TableColumnType<IQuota>[] = [
  { title: '配额类型', key: 'quota_type', dataIndex: 'quota_type', width: 160 },
  { title: '限制值', key: 'limit_value' },
  { title: '周期', key: 'period', dataIndex: 'period', width: 120 },
  { title: '更新时间', key: 'updated_at', dataIndex: 'updated_at', width: 180 },
  { title: '操作', key: 'actions', width: 100 },
]

const quotaTypeOptions: ISelectOption[] = [
  { label: 'token 限额', value: 'token_limit' },
  { label: '费用限额', value: 'cost_limit' },
  { label: '模型白名单', value: 'model_whitelist' },
]

const quotaPeriodOptions: ISelectOption[] = [
  { label: '每日', value: 'daily' },
  { label: '每周', value: 'weekly' },
  { label: '每月', value: 'monthly' },
]

async function loadDepartments(): Promise<void> {
  try {
    departments.value = await adminApi.listDepartments()
  } catch (err) {
    message.error(extractMessage(err, '加载部门列表失败'))
  }
}

async function loadQuotas(): Promise<void> {
  if (!quotaDeptId.value) {
    quotas.value = []
    return
  }
  loadingQuotas.value = true
  try {
    quotas.value = await adminApi.listDepartmentQuotas(quotaDeptId.value)
  } catch (err) {
    message.error(extractMessage(err, '加载配额列表失败'))
  } finally {
    loadingQuotas.value = false
  }
}

const quotaFormOpen = ref(false)
const submittingQuota = ref(false)
const quotaForm = reactive({
  quota_type: 'token_limit',
  period: 'daily',
})
const quotaLimitNumber = ref(0)
const quotaWhitelistText = ref('')

function openCreateQuota(): void {
  quotaForm.quota_type = 'token_limit'
  quotaForm.period = 'daily'
  quotaLimitNumber.value = 0
  quotaWhitelistText.value = ''
  quotaFormOpen.value = true
}

async function handleSubmitQuota(): Promise<void> {
  if (!quotaDeptId.value) return
  submittingQuota.value = true
  try {
    let limitValue: number | string[]
    if (quotaForm.quota_type === 'model_whitelist') {
      limitValue = quotaWhitelistText.value
        .split('\n')
        .map((s) => s.trim())
        .filter((s) => s.length > 0)
      if (limitValue.length === 0) {
        message.warning('请输入至少一个模型')
        submittingQuota.value = false
        return
      }
    } else {
      limitValue = quotaLimitNumber.value
    }
    await adminApi.setDepartmentQuota(quotaDeptId.value, {
      quota_type: quotaForm.quota_type,
      limit_value: limitValue,
      period: quotaForm.period,
    })
    message.success('配额已保存')
    quotaFormOpen.value = false
    await loadQuotas()
  } catch (err) {
    message.error(extractMessage(err, '保存配额失败'))
  } finally {
    submittingQuota.value = false
  }
}

async function handleDeleteQuota(record: IQuota): Promise<void> {
  if (!quotaDeptId.value) return
  try {
    await adminApi.deleteDepartmentQuota(quotaDeptId.value, record.quota_type, record.period)
    message.success('配额已删除')
    await loadQuotas()
  } catch (err) {
    message.error(extractMessage(err, '删除配额失败'))
  }
}

// --- Helpers ---
function extractMessage(err: unknown, fallback: string): string {
  if (err && typeof err === 'object') {
    const obj = err as { detail?: unknown; message?: unknown }
    if (typeof obj.detail === 'string' && obj.detail) return obj.detail
    if (typeof obj.message === 'string' && obj.message) return obj.message
  }
  return fallback
}

onMounted(() => {
  loadProviders()
  loadFallbacks()
  loadDepartments()
})
</script>

<style scoped>
.llm-config-view {
  padding: 24px;
  max-width: 1200px;
  margin: 0 auto;
}

.llm-config-view__header {
  margin-bottom: 16px;
}
</style>
