<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import type { Component } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { useUserStore } from '../stores/user'
import { api } from '../api/client'
import BaseButton from './ui/BaseButton.vue'
import BaseInput from './ui/BaseInput.vue'
import BaseSelect from './ui/BaseSelect.vue'
import BaseTextarea from './ui/BaseTextarea.vue'
import AnalysisAnimation from './ui/AnalysisAnimation.vue'
import {
  SparklesIcon,
  PencilSquareIcon,
  BookOpenIcon,
  PhotoIcon,
  XMarkIcon,
  ExclamationCircleIcon,
  ShieldCheckIcon,
  UserGroupIcon,
  ShareIcon,
  CheckBadgeIcon,
  ArrowPathIcon,
  HeartIcon
} from '@heroicons/vue/24/outline'

const props = defineProps<{
  modelValue: boolean
}>()

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
}>()

const { t } = useI18n()
const router = useRouter()
const userStore = useUserStore()

// State
const inputType = ref<'keywords' | 'full_story'>('keywords')
const outputMode = ref<'full_story' | 'storybook'>('full_story')
const inputData = ref('')
const educationTheme = ref('')
const loading = ref(false)
const canceling = ref(false)
const cancelRequested = ref(false)
const error = ref('')
const activeGenerationJobId = ref<string | null>(null)

// Data
interface ChildProfile {
  id: string
  name: string
}
interface StoryUniverse {
  id: string
  name: string
}
const profiles = ref<ChildProfile[]>([])
const universes = ref<StoryUniverse[]>([])
const selectedProfileId = ref('')
const selectedUniverseId = ref('')
const profileError = ref('')

// Themes
type ThemeOption = { icon: Component; label: string; value: string }
const themes: ThemeOption[] = [
  { icon: ShieldCheckIcon, label: t('home.themeCourage'), value: '勇气' },
  { icon: UserGroupIcon, label: t('home.themeFriendship'), value: '友谊' },
  { icon: ShareIcon, label: t('home.themeSharing'), value: '分享' },
  { icon: CheckBadgeIcon, label: t('home.themeHonesty'), value: '诚实' },
  { icon: ArrowPathIcon, label: t('home.themePersistence'), value: '坚持' },
  { icon: HeartIcon, label: t('home.themeTolerance'), value: '包容' },
]

const profileOptions = computed(() =>
  profiles.value.map(profile => ({ value: profile.id, label: profile.name })),
)
const universeOptions = computed(() =>
  universes.value.map(universe => ({ value: universe.id, label: universe.name })),
)
const requestedOutputMode = computed<'story' | 'storybook'>(() =>
  inputType.value === 'full_story' ? 'story' : outputMode.value === 'storybook' ? 'storybook' : 'story',
)
const generationTitle = computed(() =>
  requestedOutputMode.value === 'storybook' ? '绘本排版中...' : '故事编织中...',
)
const generationSteps = computed(() => {
  if (requestedOutputMode.value === 'storybook') {
    return [
      '正在提交后台任务...',
      'Worker 会生成绘本分镜和每页文字...',
      '主记录一落库就能通过 ID 找回...',
      '插图会继续在后台补全...',
      '稍后自动进入可翻页阅读模式。',
    ]
  }

  return [
    '正在提交后台任务...',
    'Worker 会生成故事正文并保存主记录...',
    '主内容一可读就会自动跳转详情页...',
    '封面会继续在后台补全，失败也能重试...',
    '马上进入故事详情页。',
  ]
})

interface GenerationAcceptedResponse {
  id: number | null
  generation_job_id: string | null
}

interface GenerationJobDetail {
  story_id: number | null
  status: string
  current_step: string
  is_terminal: boolean
  error_message: string | null
}

interface GenerationJobActionResponse {
  status: string
  current_step: string
}

const JOB_POLL_INTERVAL_MS = 1500
const JOB_POLL_MAX_ATTEMPTS = 80

// Methods
function close() {
  emit('update:modelValue', false)
  error.value = ''
  activeGenerationJobId.value = null
  cancelRequested.value = false
  canceling.value = false
}

function sleep(ms: number) {
  return new Promise((resolve) => {
    window.setTimeout(resolve, ms)
  })
}

async function waitForStoryId(jobId: string) {
  for (let attempt = 0; attempt < JOB_POLL_MAX_ATTEMPTS; attempt += 1) {
    const detail = await api.get<GenerationJobDetail>(`/api/generations/jobs/${jobId}`)
    if (detail.status === 'canceled' || detail.current_step === 'generation_canceled') {
      return null
    }
    if (detail.story_id) {
      return detail.story_id
    }
    if (detail.is_terminal) {
      throw new Error(detail.error_message || '生成失败，请稍后重试')
    }
    await sleep(JOB_POLL_INTERVAL_MS)
  }

  throw new Error('任务已提交，但主内容落库超时，请稍后到故事库查看最新结果')
}

async function cancelGenerationJob() {
  if (!activeGenerationJobId.value || canceling.value || cancelRequested.value) return

  canceling.value = true
  error.value = ''
  try {
    const result = await api.post<GenerationJobActionResponse>(
      `/api/generations/jobs/${activeGenerationJobId.value}/cancel`,
    )
    cancelRequested.value = true
    if (result.status === 'canceled' || result.current_step === 'generation_canceled') {
      loading.value = false
      close()
    }
  } catch (e) {
    error.value = e instanceof Error ? e.message : '取消任务失败'
  } finally {
    canceling.value = false
  }
}

async function fetchProfiles() {
  if (!userStore.user) return
  profileError.value = ''
  try {
    const data = await api.get<{ profiles: ChildProfile[] }>('/api/profiles')
    profiles.value = data.profiles
    if (!selectedProfileId.value && profiles.value.length > 0) {
      selectedProfileId.value = profiles.value[0].id
    }
  } catch (e) {
    profileError.value = e instanceof Error ? e.message : '档案加载失败'
  }
}

async function fetchUniverses(profileId: string) {
  selectedUniverseId.value = ''
  if (!profileId) {
    universes.value = []
    return
  }
  try {
    const data = await api.get<{ universes: StoryUniverse[] }>(`/api/profiles/${profileId}/universes`)
    universes.value = data.universes
    if (universes.value.length > 0) {
      selectedUniverseId.value = universes.value[0].id
    }
  } catch (e) {
    profileError.value = e instanceof Error ? e.message : '宇宙加载失败'
  }
}

watch(selectedProfileId, (newId) => {
  if (newId) fetchUniverses(newId)
})

watch(() => props.modelValue, (isOpen) => {
  if (isOpen) {
    fetchProfiles()
  }
})

async function generateStory() {
  if (!inputData.value.trim()) {
    error.value = t('home.errorEmpty')
    return
  }
  
  loading.value = true
  cancelRequested.value = false
  activeGenerationJobId.value = null
  error.value = ''

  try {
    const payload: Record<string, unknown> = {
      output_mode: requestedOutputMode.value,
      type: inputType.value,
      data: inputData.value,
      education_theme: educationTheme.value || undefined,
      generate_images: true,
      page_count: 6,
    }
    if (selectedProfileId.value) payload.child_profile_id = selectedProfileId.value
    if (selectedUniverseId.value) payload.universe_id = selectedUniverseId.value

    const accepted = await api.post<GenerationAcceptedResponse>('/api/generations', payload)
    const jobId = accepted.generation_job_id
    if (!jobId) {
      throw new Error('生成任务已创建，但缺少任务编号')
    }
    activeGenerationJobId.value = jobId

    const storyId = accepted.id ?? await waitForStoryId(jobId)
    if (storyId === null) {
      close()
      return
    }
    close()
    if (requestedOutputMode.value === 'storybook') {
      router.push(`/storybook/view/${storyId}`)
    } else {
      router.push(`/story/${storyId}`)
    }
  } catch (e) {
    error.value = e instanceof Error ? e.message : '生成失败'
  } finally {
    loading.value = false
    activeGenerationJobId.value = null
    cancelRequested.value = false
  }
}
</script>

<template>
  <Teleport to="body">
    <Transition
      enter-active-class="transition-opacity duration-300"
      enter-from-class="opacity-0"
      enter-to-class="opacity-100"
      leave-active-class="transition-opacity duration-300"
      leave-from-class="opacity-100"
      leave-to-class="opacity-0"
    >
      <div
        v-if="modelValue"
        class="fixed inset-0 z-50 flex items-center justify-center p-4"
      >
        <!-- 遮罩层 -->
        <div
          class="absolute inset-0 bg-black/60 backdrop-blur-sm"
          @click="!loading && close()"
        ></div>

        <!-- 全屏加载动画 -->
        <AnalysisAnimation
          v-if="loading"
          :title="generationTitle"
          :steps="generationSteps"
        />
        <div
          v-if="loading && activeGenerationJobId"
          class="fixed bottom-10 z-[110] flex flex-col items-center gap-3"
        >
          <BaseButton
            variant="secondary"
            :loading="canceling"
            :disabled="cancelRequested"
            @click="cancelGenerationJob"
          >
            {{ cancelRequested ? '正在取消任务...' : '取消任务' }}
          </BaseButton>
          <p class="text-sm text-white/70">
            {{ cancelRequested ? '已提交取消请求，会在安全检查点停止任务。' : '如果是误触发起，可以现在取消后台任务。' }}
          </p>
        </div>

        <!-- 模态框内容 -->
        <div v-else class="relative w-full max-w-2xl max-h-[90vh] overflow-y-auto bg-[#1C2035] border border-gray-700/50 rounded-3xl shadow-2xl p-6 md:p-8">
            <!-- 关闭按钮 -->
            <button
              @click="close"
              class="absolute top-4 right-4 p-2 rounded-full hover:bg-[var(--bg-elevated)] transition-colors z-10"
            >
              <XMarkIcon class="h-6 w-6 text-gray-400" />
            </button>

            <!-- 标题 -->
            <h2 class="text-2xl font-bold text-gray-100 mb-6">
              {{ t('home.createModalTitle') }}
            </h2>

            <!-- 输入类型切换 -->
            <div class="flex space-x-3 mb-6">
              <button
                @click="inputType = 'keywords'"
                :class="[
                  'flex-1 py-3 rounded-xl font-semibold transition-all duration-300 flex items-center justify-center space-x-2',
                  inputType === 'keywords'
                    ? 'btn-magic text-[#0D0F1A] shadow-lg bg-gradient-to-r from-[#FFD369] to-[#FF9F43]'
                    : 'bg-[#1C2035] text-gray-400 hover:border-[#FFD369] border border-white/10'
                ]"
              >
                <SparklesIcon class="h-5 w-5" />
                <span>{{ t('home.inputTypeKeywords') }}</span>
              </button>
              <button
                @click="inputType = 'full_story'"
                :class="[
                  'flex-1 py-3 rounded-xl font-semibold transition-all duration-300 flex items-center justify-center space-x-2',
                  inputType === 'full_story'
                    ? 'btn-magic text-[#0D0F1A] shadow-lg bg-gradient-to-r from-[#FFD369] to-[#FF9F43]'
                    : 'bg-[#1C2035] text-gray-400 hover:border-[#FFD369] border border-white/10'
                ]"
              >
                <PencilSquareIcon class="h-5 w-5" />
                <span>{{ t('home.inputTypeStory') }}</span>
              </button>
            </div>

            <!-- 呈现形式选择 (仅在关键词模式下可用) -->
            <div class="flex space-x-3 mb-6" v-if="inputType === 'keywords'">
              <button
                @click="outputMode = 'full_story'"
                :class="[
                  'flex-1 py-3 rounded-xl font-semibold transition-all duration-300 flex items-center justify-center space-x-2',
                  outputMode === 'full_story'
                    ? 'bg-gradient-to-r from-blue-500 to-indigo-600 text-white shadow-lg'
                    : 'bg-[#1C2035] text-gray-400 hover:border-[#FFD369] border border-white/10'
                ]"
              >
                <BookOpenIcon class="h-5 w-5" />
                <span>普通故事</span>
              </button>
              <button
                @click="outputMode = 'storybook'"
                :class="[
                  'flex-1 py-3 rounded-xl font-semibold transition-all duration-300 flex items-center justify-center space-x-2',
                  outputMode === 'storybook'
                    ? 'bg-gradient-to-r from-amber-500 to-orange-600 text-white shadow-lg'
                    : 'bg-[#1C2035] text-gray-400 hover:border-[#FFD369] border border-white/10'
                ]"
              >
                <PhotoIcon class="h-5 w-5" />
                <span>绘本模式</span>
              </button>
            </div>

            <!-- 孩子档案选择 -->
            <div class="mb-6">
              <label class="block text-gray-300 font-semibold mb-2">
                {{ t('home.selectProfile') }}
                <span class="text-gray-500 font-normal text-sm ml-1">{{ t('home.selectProfileOptional') }}</span>
              </label>
              <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                <BaseSelect
                  v-model="selectedProfileId"
                  :options="[{ value: '', label: t('home.noProfile') }, ...profileOptions]"
                />
                <BaseSelect
                  v-model="selectedUniverseId"
                  :options="[{ value: '', label: t('home.noUniverse') }, ...universeOptions]"
                  :disabled="!selectedProfileId || universes.length === 0"
                />
              </div>
              <div v-if="profileError" class="text-sm text-red-500 mt-2">{{ profileError }}</div>
              <div v-if="selectedProfileId && universes.length === 0" class="text-sm text-gray-500 mt-2">
                {{ t('home.noUniverseHint') }}
              </div>
            </div>

            <!-- 输入区域 -->
            <div class="mb-6">
              <label class="block text-gray-300 font-semibold mb-2">
                {{ inputType === 'keywords' ? t('home.inputLabel') : t('home.inputLabelStory') }}
              </label>
              <BaseTextarea
                v-model="inputData"
                :placeholder="inputType === 'keywords' ? t('home.inputPlaceholder') : t('home.inputPlaceholderStory')"
                :rows="5"
                :maxLength="5000"
              />
            </div>

            <!-- 教育主题选择 -->
            <div class="mb-6">
              <label class="block text-gray-300 font-semibold mb-2">
                {{ t('home.themeLabel') }}
                <span class="text-gray-500 font-normal text-sm ml-1">{{ t('home.themeOptional') }}</span>
              </label>
              <div class="flex flex-wrap gap-2">
                <button
                  v-for="theme in themes"
                  :key="theme.value"
                  @click="educationTheme = educationTheme === theme.value ? '' : theme.value"
                  :class="[
                    'px-4 py-2 rounded-lg font-medium transition-all duration-300 flex items-center space-x-1.5 text-sm',
                    educationTheme === theme.value
                      ? 'bg-gradient-to-r from-[#FFD369] to-[#FF9F43] text-[#0D0F1A] shadow-md'
                      : 'bg-[#1C2035] text-gray-400 hover:border-[#FFD369] border border-white/10'
                  ]"
                >
                  <component :is="theme.icon" class="h-4 w-4" />
                  <span>{{ theme.label }}</span>
                </button>
                <BaseInput
                  v-model="educationTheme"
                  :placeholder="t('home.themeCustom')"
                  class="w-28"
                />
              </div>
            </div>

            <!-- 错误提示 -->
            <Transition
              enter-active-class="transition-all duration-300"
              enter-from-class="opacity-0 -translate-y-2"
              enter-to-class="opacity-100 translate-y-0"
              leave-active-class="transition-all duration-300"
              leave-from-class="opacity-100 translate-y-0"
              leave-to-class="opacity-0 -translate-y-2"
            >
              <div v-if="error" class="mb-4 p-3 bg-red-900/20 border border-red-800 text-red-400 rounded-xl flex items-center space-x-2">
                <ExclamationCircleIcon class="h-5 w-5 flex-shrink-0" />
                <span>{{ error }}</span>
              </div>
            </Transition>

            <!-- 提交按钮 -->
            <div class="mb-4 rounded-lg border border-amber-400/20 bg-amber-300/10 px-4 py-3 text-sm text-amber-100 leading-6">
              <div class="font-semibold mb-1">
                {{ requestedOutputMode === 'storybook' ? '绘本会先保存，再补全插图' : '故事会先可读，再补全封面' }}
              </div>
              <p>
                {{ requestedOutputMode === 'storybook'
                  ? '即使部分插图暂时失败，绘本文字也会保留在故事库，稍后可以继续补全。'
                  : '封面或语音失败不会影响正文阅读，结果页会给出状态和重试入口。' }}
              </p>
            </div>

            <BaseButton
              class="w-full"
              size="lg"
              :loading="loading"
              :disabled="loading"
              @click="generateStory"
            >
              <template v-if="loading">
                {{ t('home.generating') }}
              </template>
              <template v-else>
                <SparklesIcon class="h-5 w-5 mr-2" />
                {{ t('home.startCreate') }}
              </template>
            </BaseButton>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
/* 临时添加一些 btn-magic 样式确保兼容 */
.btn-magic {
  background: linear-gradient(135deg, #FFD369 0%, #FF9F43 100%);
  color: #0D0F1A;
}
</style>
