<script setup lang="ts">
import { computed, ref, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { api } from '../api/client'
import BaseButton from '../components/ui/BaseButton.vue'
import BaseCard from '../components/ui/BaseCard.vue'
import LoadingSpinner from '../components/ui/LoadingSpinner.vue'
import EmptyState from '../components/ui/EmptyState.vue'
import CreateStoryModal from '../components/CreateStoryModal.vue'
import {
  getGenerationStatusMeta,
  isReadableGenerationStatus,
  needsGenerationAttention,
} from '../utils/storyStatus'
import {
  BookOpenIcon,
  ChevronRightIcon,
  ExclamationCircleIcon,
  PhotoIcon,
  SparklesIcon,
  PlusIcon,
} from '@heroicons/vue/24/outline'

interface StoryItem {
  id: number
  title: string
  image_url: string | null
  created_at: string
  mode: string
  generation_status: string
  text_status: string
  image_status: string
  audio_status: string
  last_error: string | null
}

interface GenerationProviderStat {
  capability: string
  adapter: string
  call_count: number
  success_count: number
  failure_count: number
  avg_latency_ms: number | null
  estimated_cost_usd: number
}

interface GenerationProviderAnalytics {
  window_days: number | null
  capability: string | null
  total_calls: number
  successful_calls: number
  failed_calls: number
  avg_latency_ms: number | null
  estimated_cost_usd: number
  job_count: number
  story_count: number
  by_provider: GenerationProviderStat[]
  failure_reasons: Array<{
    reason: string
    count: number
  }>
}

interface GenerationRecentFailure {
  job_id: string
  story_id: number | null
  story_title: string | null
  output_mode: string
  current_step: string
  error_message: string | null
  failure_label: string
  updated_at: string
}

interface GenerationOpsSummary {
  window_hours: number
  stale_threshold_minutes: number
  active_jobs: number
  stale_running_jobs: number
  failed_jobs: number
  degraded_jobs: number
  asset_retry_jobs: number
  recent_failures: GenerationRecentFailure[]
}

const router = useRouter()
const stories = ref<StoryItem[]>([])
const providerAnalytics = ref<GenerationProviderAnalytics | null>(null)
const opsSummary = ref<GenerationOpsSummary | null>(null)
const loading = ref(true)
const error = ref('')
const showCreateModal = ref(false)
const selectedWindow = ref<'7' | '30' | 'all'>('30')
const selectedCapability = ref<'all' | 'text' | 'image' | 'tts' | 'storybook'>('all')
const readableCount = computed(() =>
  stories.value.filter((story) => isReadableGenerationStatus(story.generation_status)).length,
)
const attentionCount = computed(() =>
  stories.value.filter((story) => needsGenerationAttention(story.generation_status)).length,
)
const providerSuccessRate = computed(() => {
  if (!providerAnalytics.value?.total_calls) return null
  return Math.round(
    (providerAnalytics.value.successful_calls / providerAnalytics.value.total_calls) * 100,
  )
})
const topProvider = computed(() => providerAnalytics.value?.by_provider[0] ?? null)
const topFailureReason = computed(() => providerAnalytics.value?.failure_reasons[0] ?? null)

function buildProviderAnalyticsPath() {
  const params = new URLSearchParams()
  if (selectedWindow.value !== 'all') {
    params.set('days', selectedWindow.value)
  }
  if (selectedCapability.value !== 'all') {
    params.set('capability', selectedCapability.value)
  }
  const query = params.toString()
  return `/api/generations/provider-analytics${query ? `?${query}` : ''}`
}

async function fetchStories() {
  try {
    const [storyList, analytics, ops] = await Promise.all([
      api.get<StoryItem[]>('/api/stories'),
      api.get<GenerationProviderAnalytics>(buildProviderAnalyticsPath()),
      api.get<GenerationOpsSummary>('/api/generations/ops-summary'),
    ])
    stories.value = storyList
    providerAnalytics.value = analytics
    opsSummary.value = ops
  } catch (e) {
    error.value = e instanceof Error ? e.message : '加载失败'
  } finally {
    loading.value = false
  }
}

function formatDate(dateStr: string) {
  const date = new Date(dateStr)
  const now = new Date()
  const diff = now.getTime() - date.getTime()
  const days = Math.floor(diff / (1000 * 60 * 60 * 24))

  if (days === 0) return '今天'
  if (days === 1) return '昨天'
  if (days < 7) return `${days} 天前`

  return date.toLocaleDateString('zh-CN', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  })
}

function goToCreate() {
  showCreateModal.value = true
}

function getStoryPath(story: StoryItem) {
  return story.mode === 'storybook' ? `/storybook/view/${story.id}` : `/story/${story.id}`
}

function formatLatency(value?: number | null) {
  return typeof value === 'number' ? `${Math.round(value)}ms` : '暂无'
}

function formatCost(value?: number | null) {
  return typeof value === 'number' ? `$${value.toFixed(4)}` : '$0.0000'
}

function formatOutputMode(value: string) {
  switch (value) {
    case 'storybook':
      return '绘本'
    case 'asset_retry':
      return '资源重试'
    case 'asset_generation':
      return '资源生成'
    default:
      return '故事'
  }
}

function setWindow(value: '7' | '30' | 'all') {
  selectedWindow.value = value
}

function setCapability(value: 'all' | 'text' | 'image' | 'tts' | 'storybook') {
  selectedCapability.value = value
}

onMounted(() => {
  fetchStories()
  if (router.currentRoute.value.query.openCreate) {
    showCreateModal.value = true
    router.replace({ query: { ...router.currentRoute.value.query, openCreate: undefined } })
  }
})

watch([selectedWindow, selectedCapability], () => {
  void fetchStories()
})
</script>

<template>
  <div class="max-w-6xl mx-auto px-4">
    <!-- 页面标题 -->
    <div class="flex items-center justify-between mb-8">
      <div>
        <h1 class="text-3xl font-bold gradient-text mb-2">我的故事</h1>
        <p class="text-gray-500">收藏的所有童话故事</p>
      </div>
      <BaseButton @click="goToCreate">
        <SparklesIcon class="h-5 w-5 mr-2" />
        创作新故事
      </BaseButton>
    </div>

    <!-- 加载状态 -->
    <div v-if="loading" class="py-20">
      <LoadingSpinner text="加载中..." />
    </div>

    <!-- 错误状态 -->
    <div v-else-if="error" class="py-10">
      <EmptyState
        :icon="ExclamationCircleIcon"
        title="加载失败"
        :description="error"
      />
    </div>

    <!-- 空状态 -->
    <div v-else-if="stories.length === 0" class="py-10">
      <EmptyState
        :icon="BookOpenIcon"
        title="开始你的创作之旅"
        description="还没有创作任何故事，现在就开始为孩子创作第一个专属童话故事吧！"
      >
        <template #action>
          <BaseButton @click="goToCreate">
            <PlusIcon class="h-5 w-5 mr-2" />
            创作第一个故事
          </BaseButton>
        </template>
      </EmptyState>
    </div>

    <!-- 故事列表 -->
    <template v-else>
      <!-- 统计卡片 -->
      <BaseCard class="mb-8" padding="lg">
        <div class="flex items-center justify-around divide-x divide-gray-100">
          <div class="text-center px-4">
            <div class="text-3xl font-bold text-gray-800">{{ stories.length }}</div>
            <div class="text-gray-500 text-sm mt-1">故事总数</div>
          </div>
          <div class="text-center px-4">
            <div class="text-3xl font-bold text-gray-800">
              {{ stories.filter(s => s.image_url).length }}
            </div>
            <div class="text-gray-500 text-sm mt-1">已配图</div>
          </div>
          <div class="text-center px-4">
            <div class="text-3xl font-bold text-gray-800">{{ readableCount }}</div>
            <div class="text-gray-500 text-sm mt-1">可阅读</div>
          </div>
          <div class="text-center px-4">
            <div class="text-3xl font-bold text-gray-800">{{ attentionCount }}</div>
            <div class="text-gray-500 text-sm mt-1">需关注</div>
          </div>
        </div>
      </BaseCard>

      <BaseCard
        v-if="providerAnalytics?.total_calls"
        class="mb-8"
        padding="lg"
      >
        <div class="flex flex-col gap-5 lg:flex-row lg:items-center lg:justify-between">
          <div>
            <h2 class="text-xl font-bold text-gray-800">Provider 运营摘要</h2>
            <p class="mt-2 text-sm leading-6 text-gray-500">
              生成、资源补全和失败恢复留下的供应商调用轨迹。
            </p>
            <div class="mt-4 flex flex-wrap gap-2">
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedWindow === '7' ? 'border-gray-900 bg-gray-900 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setWindow('7')">最近 7 天</button>
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedWindow === '30' ? 'border-gray-900 bg-gray-900 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setWindow('30')">最近 30 天</button>
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedWindow === 'all' ? 'border-gray-900 bg-gray-900 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setWindow('all')">全部</button>
            </div>
            <div class="mt-3 flex flex-wrap gap-2">
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedCapability === 'all' ? 'border-emerald-600 bg-emerald-600 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setCapability('all')">全部能力</button>
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedCapability === 'text' ? 'border-emerald-600 bg-emerald-600 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setCapability('text')">文本</button>
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedCapability === 'image' ? 'border-emerald-600 bg-emerald-600 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setCapability('image')">图片</button>
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedCapability === 'tts' ? 'border-emerald-600 bg-emerald-600 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setCapability('tts')">语音</button>
              <button type="button" class="rounded-lg border px-3 py-1.5 text-sm transition-colors" :class="selectedCapability === 'storybook' ? 'border-emerald-600 bg-emerald-600 text-white' : 'border-gray-200 bg-white text-gray-600 hover:border-gray-400'" @click="setCapability('storybook')">绘本</button>
            </div>
          </div>
          <div class="grid grid-cols-2 gap-3 sm:grid-cols-4 lg:min-w-[520px]">
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">成功率</div>
              <div class="mt-1 text-lg font-semibold text-gray-800">{{ providerSuccessRate }}%</div>
            </div>
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">平均耗时</div>
              <div class="mt-1 text-lg font-semibold text-gray-800">{{ formatLatency(providerAnalytics.avg_latency_ms) }}</div>
            </div>
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">预估成本</div>
              <div class="mt-1 text-lg font-semibold text-gray-800">{{ formatCost(providerAnalytics.estimated_cost_usd) }}</div>
            </div>
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">调用次数</div>
              <div class="mt-1 text-lg font-semibold text-gray-800">{{ providerAnalytics.total_calls }}</div>
            </div>
          </div>
        </div>
        <p v-if="topProvider" class="mt-4 text-sm text-gray-500">
          当前样本中最前面的能力组合是 {{ topProvider.capability }} / {{ topProvider.adapter }}，成功 {{ topProvider.success_count }} 次，失败 {{ topProvider.failure_count }} 次。
        </p>
        <p v-if="topFailureReason" class="mt-2 text-sm text-rose-600">
          最常见失败原因：{{ topFailureReason.reason }}（{{ topFailureReason.count }} 次）
        </p>
      </BaseCard>

      <BaseCard
        v-if="opsSummary"
        class="mb-8"
        padding="lg"
      >
        <div class="flex flex-col gap-5 lg:flex-row lg:items-center lg:justify-between">
          <div>
            <h2 class="text-xl font-bold text-gray-800">任务运行概览</h2>
            <p class="mt-2 text-sm leading-6 text-gray-500">
              最近 {{ opsSummary.window_hours }} 小时的任务健康度，运行超过
              {{ opsSummary.stale_threshold_minutes }} 分钟会被视为卡住。
            </p>
          </div>
          <div class="grid grid-cols-2 gap-3 sm:grid-cols-4 lg:min-w-[520px]">
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">运行中</div>
              <div class="mt-1 text-lg font-semibold text-gray-800">{{ opsSummary.active_jobs }}</div>
            </div>
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">超时待收敛</div>
              <div class="mt-1 text-lg font-semibold" :class="opsSummary.stale_running_jobs ? 'text-amber-600' : 'text-gray-800'">
                {{ opsSummary.stale_running_jobs }}
              </div>
            </div>
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">最近失败</div>
              <div class="mt-1 text-lg font-semibold" :class="opsSummary.failed_jobs ? 'text-rose-600' : 'text-gray-800'">
                {{ opsSummary.failed_jobs }}
              </div>
            </div>
            <div class="rounded-lg border border-gray-100 bg-gray-50 px-3 py-3">
              <div class="text-xs text-gray-500">资源任务</div>
              <div class="mt-1 text-lg font-semibold text-gray-800">{{ opsSummary.asset_retry_jobs }}</div>
            </div>
          </div>
        </div>
        <p v-if="opsSummary.degraded_jobs" class="mt-4 text-sm text-amber-600">
          最近 {{ opsSummary.window_hours }} 小时有 {{ opsSummary.degraded_jobs }} 个任务以降级完成收尾。
        </p>
        <div v-if="opsSummary.recent_failures.length" class="mt-4 space-y-3">
          <div
            v-for="failure in opsSummary.recent_failures"
            :key="failure.job_id"
            class="rounded-lg border border-rose-100 bg-rose-50 px-4 py-3"
          >
            <div class="flex flex-wrap items-center justify-between gap-3">
              <div class="text-sm font-semibold text-gray-800">
                {{ failure.story_title || `${formatOutputMode(failure.output_mode)}任务` }}
              </div>
              <div class="text-xs text-gray-500">{{ formatDate(failure.updated_at) }}</div>
            </div>
            <div class="mt-1 text-xs text-rose-600">
              {{ failure.failure_label }} · {{ failure.error_message || '请打开任务轨迹查看原因' }}
            </div>
          </div>
        </div>
        <p v-else class="mt-4 text-sm text-emerald-600">
          最近 {{ opsSummary.window_hours }} 小时没有失败任务，当前链路比较稳定。
        </p>
      </BaseCard>

      <!-- 故事网格 -->
      <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
        <router-link
          v-for="story in stories"
          :key="story.id"
          :to="getStoryPath(story)"
          class="block group"
        >
          <BaseCard hover padding="none" class="h-full overflow-hidden flex flex-col">
            <!-- 封面图 -->
            <div class="relative aspect-[4/3] overflow-hidden bg-gray-100">
              <img
                v-if="story.image_url"
                :src="story.image_url"
                :alt="story.title"
                class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
              />
              <div
                v-else
                class="w-full h-full flex items-center justify-center text-gray-300"
              >
                <PhotoIcon class="h-12 w-12" />
              </div>

              <div class="absolute top-4 left-4 flex flex-wrap gap-2">
                <span
                  class="px-2.5 py-1 rounded-full text-xs font-medium backdrop-blur-sm"
                  :class="story.mode === 'storybook' ? 'bg-amber-100/90 text-amber-800' : 'bg-violet-100/90 text-violet-800'"
                >
                  {{ story.mode === 'storybook' ? '绘本' : '故事' }}
                </span>
                <span
                  class="px-2.5 py-1 rounded-full text-xs font-medium backdrop-blur-sm"
                  :class="getGenerationStatusMeta(story.generation_status).badgeClass"
                >
                  {{ getGenerationStatusMeta(story.generation_status).label }}
                </span>
              </div>

              <!-- 悬停阅读提示 -->
              <div class="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
                 <span class="inline-flex items-center gap-1 px-4 py-2 bg-white/90 text-gray-900 rounded-full font-medium shadow-lg backdrop-blur-sm transform translate-y-4 group-hover:translate-y-0 transition-transform duration-300">
                    阅读故事 <ChevronRightIcon class="h-4 w-4" />
                 </span>
              </div>
            </div>

            <!-- 信息区 -->
            <div class="p-5 flex-1 flex flex-col">
              <h3 class="font-bold text-xl text-gray-800 mb-2 line-clamp-2 group-hover:text-purple-600 transition-colors">
                {{ story.title }}
              </h3>
              <p class="text-sm text-gray-500 mb-4 leading-6">
                {{ getGenerationStatusMeta(story.generation_status).description }}
              </p>
              <div class="mt-auto flex items-center justify-between text-sm text-gray-500">
                <span>{{ formatDate(story.created_at) }}</span>
                <span v-if="story.image_url" class="flex items-center gap-1 text-green-600 bg-green-50 px-2 py-0.5 rounded text-xs font-medium">
                  已配图
                </span>
              </div>
            </div>
          </BaseCard>
        </router-link>
      </div>
    </template>

    <CreateStoryModal v-model="showCreateModal" />
  </div>
</template>
