<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { computed, onMounted, reactive, ref } from 'vue';
import { http } from '../api/http';
import { useAuthStore } from '../stores/auth';

type CapabilityKey = 'text' | 'image' | 'video';

interface PlatformModelItem {
  provider: string;
  providerName: string;
  protocol: string;
  baseUrl: string;
  apiKey: string;
  modelId: string;
  modelName: string;
  endpoint: string;
  statusEndpoint?: string | null;
  resolveIp?: string | null;
  enabled: boolean;
}

type PlatformModelSettings = Record<CapabilityKey, PlatformModelItem>;

const MASKED_API_KEY = '******';
const auth = useAuthStore();
const loading = ref(false);
const saving = ref(false);

const capabilityMeta: Array<{
  key: CapabilityKey;
  title: string;
  tag: string;
  description: string;
  endpointPlaceholder: string;
  statusPlaceholder?: string;
}> = [
  {
    key: 'text',
    title: '文本模型',
    tag: '剧本 / 分镜 / 提示词',
    description: '用于大纲、剧本理解、分镜拆解、提示词生成等文本任务。',
    endpointPlaceholder: '/chat/completions',
  },
  {
    key: 'image',
    title: '图片模型',
    tag: '角色 / 场景 / 道具图',
    description: '用于角色图、场景图、道具图、封面等图片生成任务。',
    endpointPlaceholder: '/images/generations',
  },
  {
    key: 'video',
    title: '视频模型',
    tag: '分镜视频生成',
    description: '用于参考图生成视频、首尾帧生成视频等视频任务。',
    endpointPlaceholder: '/videos',
    statusPlaceholder: '/videos/{id}',
  },
];

const settings = reactive<PlatformModelSettings>({
  text: emptyItem('text'),
  image: emptyItem('image'),
  video: emptyItem('video'),
});

const canEdit = computed(() => auth.role === 'SUPER_ADMIN');

function emptyItem(key: CapabilityKey): PlatformModelItem {
  const presets = volcenginePreset(key);
  return {
    ...presets,
    apiKey: '',
    enabled: false,
  };
}

function volcenginePreset(key: CapabilityKey): PlatformModelItem {
  if (key === 'text') {
    return {
      provider: 'volcengine',
      providerName: 'Volcengine ARK',
      protocol: 'openai',
      baseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
      apiKey: MASKED_API_KEY,
      modelId: 'doubao-seed-2-0-code-preview-260215',
      modelName: 'Doubao Text',
      endpoint: '/chat/completions',
      statusEndpoint: '',
      resolveIp: '',
      enabled: false,
    };
  }
  if (key === 'image') {
    return {
      provider: 'volcengine',
      providerName: 'Volcengine ARK',
      protocol: 'seedream',
      baseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
      apiKey: MASKED_API_KEY,
      modelId: 'doubao-seedream-5-0-260128',
      modelName: 'Seedream Image',
      endpoint: '/images/generations',
      statusEndpoint: '',
      resolveIp: '',
      enabled: false,
    };
  }
  return {
    provider: 'volcengine',
    providerName: 'Volcengine ARK',
    protocol: 'seedance',
    baseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
    apiKey: MASKED_API_KEY,
    modelId: 'doubao-seedance-2-0-fast-260128',
    modelName: 'Seedance Image-to-Video',
    endpoint: '/contents/generations/tasks',
    statusEndpoint: '/contents/generations/tasks/{id}',
    resolveIp: '',
    enabled: false,
  };
}

function agnesPreset(key: CapabilityKey): PlatformModelItem {
  const common = {
    provider: 'agnes',
    providerName: 'Agnes',
    protocol: 'openai',
    baseUrl: 'https://apihub.agnes-ai.com/v1',
    apiKey: settings[key].apiKey || '',
    resolveIp: settings[key].resolveIp || '104.18.18.62',
    enabled: true,
  };
  if (key === 'text') {
    return {
      ...common,
      modelId: 'agnes-2.0-flash',
      modelName: 'Agnes 2.0 Flash',
      endpoint: '/chat/completions',
      statusEndpoint: '',
    };
  }
  if (key === 'image') {
    return {
      ...common,
      modelId: 'agnes-image-2.0-flash',
      modelName: 'Agnes Image 2.0 Flash',
      endpoint: '/images/generations',
      statusEndpoint: '',
    };
  }
  return {
    ...common,
    modelId: 'agnes-video-v2.0',
    modelName: 'Agnes Video v2.0',
    endpoint: '/videos',
    statusEndpoint: '/videos/{id}',
  };
}

function applyPreset(key: CapabilityKey, type: 'agnes' | 'volcengine') {
  const oldApiKey = settings[key].apiKey;
  Object.assign(settings[key], type === 'agnes' ? agnesPreset(key) : volcenginePreset(key));
  settings[key].apiKey = oldApiKey || settings[key].apiKey;
}

function normalizeItem(key: CapabilityKey, item?: Partial<PlatformModelItem> | null): PlatformModelItem {
  return {
    ...emptyItem(key),
    ...(item || {}),
    enabled: Boolean(item?.enabled),
  };
}

async function load() {
  loading.value = true;
  try {
    const data = await http.get<Partial<PlatformModelSettings>>('/model-config');
    for (const meta of capabilityMeta) {
      Object.assign(settings[meta.key], normalizeItem(meta.key, data?.[meta.key]));
    }
  } finally {
    loading.value = false;
  }
}

function validate() {
  for (const meta of capabilityMeta) {
    const item = settings[meta.key];
    if (!item.enabled) continue;
    if (!item.baseUrl || !item.apiKey || !item.modelId || !item.endpoint) {
      ElMessage.warning(`${meta.title} 启用后需要填写 Base URL、API Key、模型 ID 和调用路径`);
      return false;
    }
  }
  return true;
}

function buildPayload(): PlatformModelSettings {
  return {
    text: { ...settings.text },
    image: { ...settings.image },
    video: { ...settings.video },
  };
}

async function save() {
  if (!validate()) return;
  saving.value = true;
  try {
    const data = await http.put<PlatformModelSettings>('/model-config', buildPayload());
    for (const meta of capabilityMeta) {
      Object.assign(settings[meta.key], normalizeItem(meta.key, data?.[meta.key]));
    }
    ElMessage.success('模型配置已保存，新生成任务将读取这份配置');
  } finally {
    saving.value = false;
  }
}

onMounted(load);
</script>

<template>
  <div>
    <div class="page-head">
      <div>
        <h1>模型配置</h1>
        <p>统一配置平台默认的文本、图片、视频模型。未启用时继续使用后端环境变量里的火山引擎配置。</p>
      </div>
      <el-button type="primary" :disabled="!canEdit" :loading="saving" @click="save">保存配置</el-button>
    </div>

    <el-alert
      class="model-tip"
      type="info"
      show-icon
      :closable="false"
      title="API Key 保存后会以 ****** 显示；保持 ****** 或留空保存时，会继续沿用旧密钥。"
    />

    <div v-loading="loading" class="model-grid">
      <el-card v-for="meta in capabilityMeta" :key="meta.key" class="model-card" shadow="never">
        <template #header>
          <div class="card-head">
            <div>
              <strong>{{ meta.title }}</strong>
              <span>{{ meta.tag }}</span>
            </div>
            <el-switch v-model="settings[meta.key].enabled" :disabled="!canEdit" active-text="启用配置" />
          </div>
        </template>

        <p class="card-desc">{{ meta.description }}</p>

        <div class="preset-row">
          <el-button size="small" @click="applyPreset(meta.key, 'agnes')">填入 Agnes 模板</el-button>
          <el-button size="small" @click="applyPreset(meta.key, 'volcengine')">恢复火山模板</el-button>
        </div>

        <el-form label-position="top" class="model-form" :disabled="!canEdit">
          <div class="form-pair">
            <el-form-item label="供应商 Key">
              <el-input v-model="settings[meta.key].provider" placeholder="agnes / volcengine" />
            </el-form-item>
            <el-form-item label="供应商名称">
              <el-input v-model="settings[meta.key].providerName" placeholder="Agnes" />
            </el-form-item>
          </div>

          <div class="form-pair">
            <el-form-item label="协议">
              <el-select v-model="settings[meta.key].protocol">
                <el-option label="OpenAI Compatible" value="openai" />
                <el-option label="Seedream" value="seedream" />
                <el-option label="Seedance" value="seedance" />
              </el-select>
            </el-form-item>
            <el-form-item label="Base URL">
              <el-input v-model="settings[meta.key].baseUrl" placeholder="https://apihub.agnes-ai.com/v1" />
            </el-form-item>
          </div>

          <el-form-item label="API Key">
            <el-input
              v-model="settings[meta.key].apiKey"
              type="password"
              show-password
              placeholder="粘贴供应商 API Key"
            />
          </el-form-item>

          <div class="form-pair">
            <el-form-item label="模型 ID">
              <el-input v-model="settings[meta.key].modelId" placeholder="agnes-2.0-flash" />
            </el-form-item>
            <el-form-item label="模型名称">
              <el-input v-model="settings[meta.key].modelName" placeholder="展示在计费与日志里的名称" />
            </el-form-item>
          </div>

          <div class="form-pair">
            <el-form-item label="调用路径">
              <el-input v-model="settings[meta.key].endpoint" :placeholder="meta.endpointPlaceholder" />
            </el-form-item>
            <el-form-item label="查询路径">
              <el-input
                v-model="settings[meta.key].statusEndpoint"
                :disabled="!canEdit || meta.key !== 'video'"
                :placeholder="meta.statusPlaceholder || '仅视频模型需要'"
              />
            </el-form-item>
          </div>

          <el-form-item label="解析 IP（可选）">
            <el-input v-model="settings[meta.key].resolveIp" placeholder="DNS 异常时填写，如 104.18.18.62" />
          </el-form-item>
        </el-form>
      </el-card>
    </div>
  </div>
</template>

<style scoped>
.model-tip {
  margin-bottom: 16px;
}

.model-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(280px, 1fr));
  gap: 16px;
  align-items: start;
}

.model-card {
  border-color: var(--line);
  border-radius: 8px;
}

.card-head {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: center;
}

.card-head strong {
  display: block;
  font-size: 17px;
}

.card-head span,
.card-desc {
  color: var(--muted);
  font-size: 13px;
}

.card-desc {
  margin: 0 0 12px;
  line-height: 1.6;
}

.preset-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.model-form :deep(.el-form-item) {
  margin-bottom: 12px;
}

.form-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

@media (max-width: 1280px) {
  .model-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 720px) {
  .form-pair {
    grid-template-columns: 1fr;
  }
}
</style>
