<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="700px">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="100px"
      v-loading="formLoading"
    >
      <!-- 基础信息 -->
      <el-divider content-position="left">基础信息</el-divider>
      <el-form-item label="角色名称" prop="name">
        <el-input v-model="formData.name" placeholder="如：Katie Leona" />
      </el-form-item>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="性别" prop="gender">
            <el-select v-model="formData.gender" placeholder="请选择性别">
              <el-option label="男" value="male" />
              <el-option label="女" value="female" />
              <el-option label="其他" value="other" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="年龄段" prop="ageRange">
            <el-input v-model="formData.ageRange" placeholder="如：20s、25-30" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="头像" prop="avatarUrl">
            <div class="flex items-center gap-12px">
              <el-avatar v-if="formData.avatarUrl" :src="formData.avatarUrl" :size="50" />
              <el-button type="primary" plain @click="avatarInputRef?.click()">
                {{ formData.avatarUrl ? '重新上传' : '选择图片' }}
              </el-button>
              <el-button v-if="formData.avatarUrl" type="danger" plain @click="formData.avatarUrl = undefined">
                删除
              </el-button>
              <input
                ref="avatarInputRef"
                type="file"
                accept="image/*"
                class="hidden"
                @change="onAvatarFileChange"
              />
            </div>
            <!-- 头像裁剪弹窗 -->
            <Dialog v-model="cropperVisible" title="裁剪头像（50 x 50）" width="800px" :canFullscreen="false">
              <div class="flex gap-20px">
                <div class="flex-1">
                  <CropperImage
                    v-if="avatarCropSrc"
                    :src="avatarCropSrc"
                    height="300px"
                    :options="{ aspectRatio: 1, viewMode: 1 }"
                    @ready="onCropperReady"
                    @cropend="onCropend"
                  />
                </div>
                <div class="flex flex-col items-center justify-center">
                  <div class="w-50px h-50px overflow-hidden border border-gray-300 rounded-full">
                    <img v-if="avatarPreview" :src="avatarPreview" class="w-full h-full" />
                  </div>
                  <span class="mt-8px text-12px text-gray-400">50 x 50 预览</span>
                </div>
              </div>
              <template #footer>
                <el-button @click="cropperVisible = false">取消</el-button>
                <el-button type="primary" :loading="avatarUploading" @click="confirmCropAvatar">
                  确认上传
                </el-button>
              </template>
            </Dialog>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="封面图" prop="coverImageUrl">
            <UploadImg v-model="formData.coverImageUrl" directory="ai_companion_cover" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="一句话简介" prop="shortDesc">
        <el-input v-model="formData.shortDesc" placeholder="用于卡片或列表展示" />
      </el-form-item>
      <el-form-item label="详细介绍" prop="introText">
        <el-input v-model="formData.introText" type="textarea" :rows="3" placeholder="用于角色详情页" />
      </el-form-item>
      <!-- 人设配置 -->
      <el-divider content-position="left">人设配置</el-divider>
      <el-form-item label="性格标签" prop="personalityTags">
        <div class="w-full">
          <div class="flex flex-wrap">
            <el-tag
              v-for="(tag, index) in formData.personalityTags"
              :key="index"
              class="mr-5px mb-5px"
              closable
              @close="removeTag(index)"
            >
              {{ tag }}
            </el-tag>
            <span v-if="!formData.personalityTags?.length" class="text-gray-400">暂无标签</span>
          </div>
          <div class="mt-8px flex items-center gap-8px">
            <el-input v-model="newTag" placeholder="输入标签后回车" class="!w-200px" @keyup.enter="addTag" />
            <el-button type="primary" plain @click="addTag">添加</el-button>
          </div>
        </div>
      </el-form-item>
      <el-form-item label="说话风格" prop="speakingStyle">
        <el-input v-model="formData.speakingStyle" placeholder="如：撒娇型、理性型、活泼型" />
      </el-form-item>
      <el-form-item label="系统 Prompt" prop="systemPrompt">
        <el-input
          v-model="formData.systemPrompt"
          type="textarea"
          :rows="5"
          placeholder="定义角色核心人设，仅供 AI 模型使用"
        />
      </el-form-item>

      <!-- 语音与开场白 -->
      <el-divider content-position="left">语音与开场白</el-divider>
      <el-form-item label="开场白" prop="prologue">
        <el-input v-model="formData.prologue" type="textarea" :rows="2" placeholder="角色的开场白文案" />
      </el-form-item>
      <el-form-item label="开场白音频" prop="prologueAudio">
        <el-input v-model="formData.prologueAudio" placeholder="开场白音频 URL" />
      </el-form-item>
      <el-form-item label="音色 ID" prop="voiceId">
        <el-input v-model="formData.voiceId" placeholder="TTS 音色 ID" />
      </el-form-item>

      <!-- 运营配置 -->
      <el-divider content-position="left">运营配置</el-divider>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="状态" prop="status">
            <el-radio-group v-model="formData.status">
              <el-radio :value="1">上线</el-radio>
              <el-radio :value="0">下线</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="可见性" prop="visibility">
            <el-select v-model="formData.visibility" placeholder="请选择可见性">
              <el-option label="公开" :value="1" />
              <el-option label="内测" :value="2" />
              <el-option label="隐藏" :value="3" />
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="排序权重" prop="sortOrder">
            <el-input-number v-model="formData.sortOrder" :min="0" controls-position="right" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="热度评分" prop="popularityScore">
            <el-input-number v-model="formData.popularityScore" :min="0" :precision="1" controls-position="right" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { AiCompanionApi, AiCompanion } from '@/api/keyboard/aicompanion'
import { UploadImg } from '@/components/UploadFile'
import { CropperImage } from '@/components/Cropper'
import * as FileApi from '@/api/infra/file'
import type { Cropper } from 'cropperjs'

defineOptions({ name: 'AiCompanionForm' })

const { t } = useI18n()
const message = useMessage()

const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const formData = ref({
  id: undefined,
  name: undefined,
  avatarUrl: undefined,
  coverImageUrl: undefined,
  gender: undefined,
  ageRange: undefined,
  shortDesc: undefined,
  introText: undefined,
  personalityTags: [] as string[],
  speakingStyle: undefined,
  systemPrompt: undefined,
  status: 1,
  visibility: 1,
  sortOrder: 0,
  popularityScore: 0,
  prologue: undefined,
  prologueAudio: undefined,
  voiceId: undefined
})
const formRules = reactive({
  name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }],
  systemPrompt: [{ required: true, message: '系统 Prompt 不能为空', trigger: 'blur' }],
  status: [{ required: true, message: '请选择状态', trigger: 'change' }],
  visibility: [{ required: true, message: '请选择可见性', trigger: 'change' }]
})
const formRef = ref()

/** 头像裁剪上传 */
const avatarInputRef = ref<HTMLInputElement>()
const cropperVisible = ref(false)
const avatarCropSrc = ref('')
const avatarPreview = ref('')
const avatarUploading = ref(false)
let cropperInstance: Cropper | null = null

const onAvatarFileChange = (e: Event) => {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = (ev) => {
    avatarCropSrc.value = (ev.target?.result as string) ?? ''
    avatarPreview.value = ''
    cropperVisible.value = true
  }
  reader.readAsDataURL(file)
  // 清空 input 以便重复选择同一文件
  ;(e.target as HTMLInputElement).value = ''
}
const onCropperReady = (cropper: Cropper) => {
  cropperInstance = cropper
}
const onCropend = ({ imgBase64 }: { imgBase64: string }) => {
  avatarPreview.value = imgBase64
}
const confirmCropAvatar = async () => {
  if (!cropperInstance) return
  const canvas = cropperInstance.getCroppedCanvas({ width: 50, height: 50 })
  canvas.toBlob(async (blob) => {
    if (!blob) return
    avatarUploading.value = true
    try {
      const file = new File([blob], 'avatar.png', { type: 'image/png' })
      const res = await FileApi.updateFile({ file, directory: 'ai_companion_avatar' })
      formData.value.avatarUrl = res.data
      cropperVisible.value = false
      message.success('头像上传成功')
    } finally {
      avatarUploading.value = false
    }
  }, 'image/png')
}

/** 性格标签 */
const newTag = ref('')
const normalizePersonalityTags = (raw: unknown): string[] => {
  if (!raw) return []
  if (Array.isArray(raw)) return raw.map(String)
  if (typeof raw === 'string') {
    try {
      const parsed = JSON.parse(raw)
      if (Array.isArray(parsed)) return parsed.map(String)
    } catch {
      return raw.split(/[,，]/).map((s) => s.trim()).filter(Boolean)
    }
  }
  return []
}
const addTag = () => {
  const text = newTag.value.trim()
  if (!text) return
  if (!formData.value.personalityTags.includes(text)) {
    formData.value.personalityTags = [...formData.value.personalityTags, text]
  }
  newTag.value = ''
}
const removeTag = (index: number) => {
  formData.value.personalityTags = formData.value.personalityTags.filter((_, i) => i !== index)
}

/** 打开弹窗 */
const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  resetForm()
  if (id) {
    formLoading.value = true
    try {
      const data = await AiCompanionApi.getAiCompanion(id)
      formData.value = {
        ...data,
        personalityTags: normalizePersonalityTags(data.personalityTags)
      }
    } finally {
      formLoading.value = false
    }
  }
}
defineExpose({ open })

/** 提交表单 */
const emit = defineEmits(['success'])
const submitForm = async () => {
  await formRef.value.validate()
  formLoading.value = true
  try {
    const data = formData.value as unknown as AiCompanion
    if (formType.value === 'create') {
      await AiCompanionApi.createAiCompanion(data)
      message.success(t('common.createSuccess'))
    } else {
      await AiCompanionApi.updateAiCompanion(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined,
    name: undefined,
    avatarUrl: undefined,
    coverImageUrl: undefined,
    gender: undefined,
    ageRange: undefined,
    shortDesc: undefined,
    introText: undefined,
    personalityTags: [] as string[],
    speakingStyle: undefined,
    systemPrompt: undefined,
    status: 1,
    visibility: 1,
    sortOrder: 0,
    popularityScore: 0,
    prologue: undefined,
    prologueAudio: undefined,
    voiceId: undefined
  }
  formRef.value?.resetFields()
}
</script>
