<script lang="ts">
export default { name: 'CharactersView' }
</script>
<template>
  <div class="char-page page-fullscreen">
    <PageHeader title="画作角色" :subtitle="subtitle" :step="1" />

    <div class="content page-content">
      <!-- 加载中 -->
      <div v-if="loading" class="loading-state">
        <loading-outlined class="loading-spinner" spin />
        <div class="loading-title">AI 正在识别角色…</div>
        <div class="loading-sub">通常需要 10-20 秒</div>
      </div>

      <!-- 错误状态 -->
      <template v-else-if="error">
        <div class="error-state">
          <frown-outlined class="error-icon" />
          <div class="error-text">{{ error }}</div>
          <button class="btn-ghost back-btn" @click="$router.back()">返回重新上传</button>
        </div>
      </template>

      <!-- 单角色：大图展示 -->
      <template v-else-if="characters.length === 1">
        <div class="single-wrap">
          <div class="single-card">
            <div class="single-img-wrap">
              <img v-if="characters[0].originalCropUrl" :src="characters[0].originalCropUrl" class="single-img" />
              <user-outlined v-else class="single-placeholder" />
              <div class="zoom-hint"
                @click.stop="characters[0].originalCropUrl && (previewImg = characters[0].originalCropUrl)">
                <zoom-in-outlined />
              </div>
            </div>
          </div>
          <div class="single-tip">
            <check-circle-filled />
            <span>AI 识别到 1 个角色，将作为绘本主角</span>
          </div>
        </div>
      </template>

      <!-- 多角色：网格选择 -->
      <template v-else>
        <div class="result-tip">
          <check-circle-filled class="result-icon" />
          <span>AI 识别到 <strong>{{ characters.length }}</strong> 个角色，选一个作为主角</span>
        </div>

        <div class="char-grid">
          <div v-for="c in characters" :key="c.charId" class="char-card" :class="{ selected: selected === c.charId }"
            @click="selected = c.charId">
            <!-- 推荐角标 -->
            <div v-if="c.type === 'HERO'" class="hero-badge">
              <crown-filled />
              <span>推荐</span>
            </div>
            <!-- 选中角标 -->
            <div v-if="selected === c.charId" class="check-badge">
              <check-outlined />
            </div>
            <!-- 头像 -->
            <div class="char-img-wrap">
              <img v-if="c.originalCropUrl" :src="c.originalCropUrl" class="char-img" />
              <user-outlined v-else class="char-placeholder" />
              <div class="zoom-hint" @click.stop="c.originalCropUrl && (previewImg = c.originalCropUrl)">
                <zoom-in-outlined />
              </div>
            </div>
          </div>
        </div>
      </template>

      <!-- 图片预览 -->
      <Transition name="fade">
        <div v-if="previewImg" class="preview-overlay" @click="previewImg = ''">
          <img :src="previewImg" class="preview-full-img" />
        </div>
      </Transition>
    </div>

    <div class="page-bottom">
      <button class="btn-primary next-btn" :disabled="!canNext" @click="goNext">
        <span>{{ nextLabel }}</span>
        <arrow-right-outlined />
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onActivated } from 'vue'
import { useRouter } from 'vue-router'
import {
  LoadingOutlined,
  FrownOutlined,
  CheckCircleFilled,
  UserOutlined,
  CrownFilled,
  CheckOutlined,
  ArrowRightOutlined,
  ZoomInOutlined,
} from '@ant-design/icons-vue'

import PageHeader from '@/components/aicreate/PageHeader.vue'
import { useAicreateStore } from '@/stores/aicreate'
import { extractCharacters } from '@/api/aicreate'
import { saveExtractDraft } from '@/utils/aicreate/extractDraft'

const router = useRouter()
const store = useAicreateStore()
const loading = ref(true)
const selected = ref<string | null>(null)
const characters = ref<any[]>([])
const error = ref('')
const previewImg = ref('')

const subtitle = computed(() => {
  if (loading.value) return 'AI 正在识别画中的角色'
  if (error.value) return ''
  if (characters.value.length === 0) return ''
  if (characters.value.length === 1) return 'AI 识别出的角色形象'
  return 'AI 识别出多个角色，选一个作为主角'
})

const canNext = computed(() => {
  if (characters.value.length === 1) return true
  return !!selected.value
})

const nextLabel = computed(() => {
  if (characters.value.length === 1) return '使用此角色，编排故事'
  return '确定主角，编排故事'
})

async function loadCharacters() {
  if (store.characters && store.characters.length > 0) {
    characters.value = store.characters
    autoSelect()
    loading.value = false
    return
  }

  if (!store.imageUrl) {
    error.value = '未上传图片，请返回上传'
    loading.value = false
    return
  }
  try {
    const res = await extractCharacters(store.imageUrl)
    const data = res || {}
    characters.value = (data.characters || []).map((c: any) => ({
      ...c,
      type: c.charType || c.type || 'SIDEKICK'
    }))
    if (characters.value.length === 0) {
      error.value = 'AI 未识别到角色，请更换图片重试'
    }
    store.extractId = data.extractId || ''
    store.characters = characters.value
    autoSelect()
    if (characters.value.length > 0) {
      saveExtractDraft({
        imageUrl: store.imageUrl,
        extractId: store.extractId,
        characters: characters.value,
        raw: data,
      })
    }
  } catch (e: any) {
    error.value = '角色识别失败：' + (e.message || '请检查网络')
  } finally {
    loading.value = false
  }
}

onActivated(() => {
  void loadCharacters()
})

function autoSelect() {
  if (characters.value.length === 1) {
    selected.value = characters.value[0].charId
    return
  }
  const hero = characters.value.find(c => c.type === 'HERO')
  if (hero) selected.value = hero.charId
}

const goNext = () => {
  // 单角色直接用第一个，多角色用 selected
  const target = characters.value.length === 1
    ? characters.value[0]
    : characters.value.find(c => c.charId === selected.value)
  store.selectedCharacter = target
  router.push('/p/create/story')
}
</script>

<style lang="scss" scoped>
.char-page {
  min-height: 100vh;
  background: var(--ai-bg);
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
}

/* ---------- 加载状态 ---------- */
.loading-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 0;
}

.loading-spinner {
  font-size: 44px;
  color: var(--ai-primary);
  margin-bottom: 18px;
}

.loading-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--ai-text);
}

.loading-sub {
  font-size: 13px;
  color: var(--ai-text-sub);
  margin-top: 6px;
}

/* ---------- 错误状态 ---------- */
.error-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 60px 0;
}

.error-icon {
  font-size: 48px;
  color: var(--ai-text-sub);
}

.error-text {
  font-size: 15px;
  font-weight: 600;
  color: var(--ai-text);
  text-align: center;
}

.back-btn {
  max-width: 200px;
  margin-top: 8px;
}

/* ---------- 单角色大图 ---------- */
.single-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 12px 0 24px;
}

.single-card {
  width: 100%;
  max-width: 360px;
  background: #fff;
  border: 2px solid var(--ai-primary);
  border-radius: 26px;
  padding: 14px;
  box-shadow: 0 14px 36px rgba(99, 102, 241, 0.22);
}

.single-img-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 20px;
  overflow: hidden;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(236, 72, 153, 0.08));
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover .zoom-hint {
    opacity: 1;
  }

  &:active {
    transform: scale(0.98);
  }
}

.single-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.single-placeholder {
  font-size: 72px;
  color: var(--ai-text-sub);
}

.single-tip {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--ai-text);
  font-weight: 600;

  :deep(.anticon) {
    color: var(--ai-primary);
    font-size: 18px;
  }
}

/* ---------- 多角色结果提示 ---------- */
.result-tip {
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(236, 72, 153, 0.05));
  border: 1px solid rgba(99, 102, 241, 0.15);
  border-radius: var(--ai-radius-sm);
  padding: 12px 16px;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--ai-text);
  font-weight: 500;

  strong {
    color: var(--ai-primary);
    font-weight: 800;
    margin: 0 2px;
  }
}

.result-icon {
  font-size: 18px;
  color: var(--ai-primary);
  flex-shrink: 0;
}

/* ---------- 多角色网格 ---------- */
.char-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
}

.char-card {
  position: relative;
  background: #fff;
  border-radius: var(--ai-radius);
  padding: 10px;
  border: 2px solid transparent;
  transition: all 0.25s ease;
  cursor: pointer;
  box-shadow: 0 2px 12px rgba(99, 102, 241, 0.05);

  &:hover {
    border-color: rgba(99, 102, 241, 0.18);
    box-shadow: 0 4px 16px rgba(99, 102, 241, 0.1);
  }

  &.selected {
    border-color: var(--ai-primary);
    background: linear-gradient(135deg, rgba(99, 102, 241, 0.04), rgba(236, 72, 153, 0.03));
    box-shadow: 0 8px 24px rgba(99, 102, 241, 0.18);
  }

  &:active {
    transform: scale(0.99);
  }
}

.char-img-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 14px;
  overflow: hidden;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.08), rgba(236, 72, 153, 0.06));
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover .zoom-hint {
    opacity: 1;
  }
}

.char-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.char-placeholder {
  font-size: 36px;
  color: var(--ai-text-sub);
}

.hero-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 10px;
  background: linear-gradient(135deg, #6366f1, #ec4899);
  color: #fff;
  padding: 3px 7px;
  border-radius: 8px;
  font-weight: 700;
  box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);

  :deep(.anticon) {
    font-size: 9px;
  }
}

.check-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 2;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--ai-gradient);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
}

.zoom-hint {
  position: absolute;
  right: 6px;
  bottom: 6px;
  z-index: 3;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(15, 12, 41, 0.55);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  opacity: 0.7;
  cursor: pointer;
  transition: opacity 0.2s;
}

/* ---------- 底部按钮 ---------- */
.next-btn {
  display: flex !important;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 16px !important;
  padding: 14px 0 !important;
  border-radius: 28px !important;

  :deep(.anticon) {
    font-size: 16px;
  }
}

/* ---------- 图片预览 ---------- */
.preview-overlay {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: rgba(15, 12, 41, 0.88);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}

.preview-full-img {
  max-width: 90%;
  max-height: 80vh;
  object-fit: contain;
  border-radius: 16px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.2s;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>
