<template>
  <div class="ideas">
    <header class="page-header">
      <h1>{{ $t('ideas.title') }}</h1>
      <div class="header-actions">
        <button class="btn btn-ghost" @click="refresh">{{ $t('ideas.refresh') }}</button>
        <button class="btn btn-primary" @click="openCaptureModal">{{ $t('ideas.capture') }}</button>
      </div>
    </header>

    <!-- 搜索和筛选栏 -->
    <div class="filter-bar">
      <div class="search-box">
        <input
          v-model="searchQuery"
          type="text"
          :placeholder="$t('ideas.searchPlaceholder')"
        />
      </div>
      <button
        v-for="f in filters"
        :key="f.key"
        class="filter-btn"
        :class="{ active: activeFilter === f.key }"
        @click="activeFilter = f.key"
      >
        {{ f.icon }} {{ $t(f.labelKey) }}
      </button>
      <!-- 排序切换:score 高分在前 / time 新在前 -->
      <div class="sort-group">
        <button
          class="filter-btn"
          :class="{ active: sortMode === 'score' }"
          @click="sortMode = 'score'"
        >{{ $t('ideas.sortByScore') }}</button>
        <button
          class="filter-btn"
          :class="{ active: sortMode === 'time' }"
          @click="sortMode = 'time'"
        >{{ $t('ideas.sortByTime') }}</button>
      </div>
    </div>

    <!-- 两栏布局 -->
    <div class="ideas-layout">
      <!-- 左侧：灵感列表 -->
      <section class="idea-list-panel">
        <div class="idea-list">
          <!-- 三态:加载/错误/空(对齐 Tasks.vue:43-45) -->
          <div v-if="store.loading" class="empty-state">{{ $t('common.loading') }}</div>
          <div v-else-if="store.error" class="empty-state">{{ store.error }}</div>
          <div v-else-if="filteredIdeas.length === 0" class="empty-state">{{ $t('ideas.listEmpty') }}</div>
          <template v-else>
            <div
              v-for="idea in pagedIdeas"
              :key="idea.id"
              class="idea-card"
              :class="{ selected: selectedId === idea.id }"
              @click="selectedId = idea.id"
            >
              <div class="idea-card-header">
                <span class="idea-title">{{ idea.title }}</span>
                <span class="idea-score" :class="scoreClass(idea.score)">{{ idea.score ?? '-' }}</span>
              </div>
              <p class="idea-desc-preview">{{ stripMd(idea.description).slice(0, 60) }}{{ stripMd(idea.description).length > 60 ? '...' : '' }}</p>
              <div class="idea-card-footer">
                <span class="status-tag" :class="'status-' + idea.status">{{ $t(statusLabelKey(idea.status)) }}</span>
                <span class="idea-date">{{ formatDate(idea.created_at) }}</span>
              </div>
            </div>
          </template>
        </div>
        <!-- 分页器(F-260621-02 P3):pageSize=0 不分页(全量,等价旧行为);用户选 N 条触发客户端切片 -->
        <Paginator
          v-model:page="page"
          v-model:pageSize="pageSize"
          :total="filteredIdeas.length"
        />
      </section>

      <!-- 右侧：灵感详情 -->
      <IdeaDetail
        v-if="currentIdea"
        :idea="currentIdea"
        :evaluating="evaluating"
        :eval-error="evalError"
        :promoting="promoting"
        :deleting="deleting"
        :status-options="statusOptions"
        @evaluate="evaluateCurrentIdea"
        @promote="promoteToProject"
        @delete="deleteCurrentIdea"
        @status-change="onStatusChange"
        @update-desc="onUpdateDesc"
        @update-related="onUpdateRelated"
      />

      <!-- 未选择 -->
      <section class="idea-detail-panel idea-empty" v-else>
        <div class="empty-state">
          <div class="empty-icon">💡</div>
          <p>{{ $t('ideas.emptyState') }}</p>
        </div>
      </section>
    </div>

    <!-- 捕捉灵感模态框 -->
    <div class="modal-overlay" v-if="showCaptureModal" @click.self="showCaptureModal = false">
      <div class="modal-box">
        <h3>{{ $t('ideas.captureTitle') }}</h3>
        <div class="modal-field">
          <label>{{ $t('ideas.fieldTitle') }}</label>
          <input v-model="newIdeaTitle" :placeholder="$t('ideas.titlePlaceholder')" @keyup.enter="confirmCapture" />
        </div>
        <div class="modal-field">
          <label>{{ $t('ideas.fieldDesc') }}</label>
          <textarea v-model="newIdeaDesc" :placeholder="$t('ideas.descPlaceholder')" rows="3" style="resize:vertical"></textarea>
        </div>
        <div class="modal-field">
          <label>{{ $t('ideas.fieldTags') }}</label>
          <input v-model="newIdeaTags" :placeholder="$t('ideas.tagsPlaceholder')" />
        </div>
        <div class="modal-field">
          <label>{{ $t('ideas.fieldPriority') }}</label>
          <select v-model.number="newIdeaPriority" class="modal-select">
            <option :value="0">{{ $t('ideas.priorityCritical') }} (P0)</option>
            <option :value="1">{{ $t('ideas.priorityHigh') }} (P1)</option>
            <option :value="2">{{ $t('ideas.priorityMedium') }} (P2)</option>
            <option :value="3">{{ $t('ideas.priorityLow') }} (P3)</option>
          </select>
        </div>
        <div class="modal-field">
          <label>{{ $t('ideas.fieldSource') }}</label>
          <input v-model="newIdeaSource" :placeholder="$t('ideas.sourcePlaceholder')" />
        </div>
        <div class="modal-actions">
          <button class="btn btn-ghost" @click="showCaptureModal = false">{{ $t('common.cancel') }}</button>
          <button class="btn btn-primary" :disabled="creating" @click="confirmCapture">
            {{ creating ? $t('ideas.creating') : $t('common.confirm') }}
          </button>
        </div>
      </div>
    </div>

    <!-- 确认弹层（删除灵感，替代原生 window.confirm） -->
    <ConfirmDialog :visible="confirmState.visible" :msg="confirmState.msg" @result="answerConfirm" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { Message } from '@arco-design/web-vue'
import { useProjectStore } from '../stores/project'
import type { IdeaStatus, IdeaQuery } from '../api/types'
import { formatDate } from '../utils/time'
import { stripMd } from '../utils/markdown'
import { scoreTier } from '../utils/ideaEval'
import ConfirmDialog from '../components/ConfirmDialog.vue'
import IdeaDetail from '../components/ideas/IdeaDetail.vue'
import { useConfirm } from '../composables/useConfirm'
import { usePersistedRef } from '../composables/usePersistedRef'
import Paginator from '../components/Paginator.vue'

const { t } = useI18n()
const router = useRouter()
const route = useRoute()
const store = useProjectStore()

// 确认弹层状态机抽至 composables/useConfirm(原 4 视图重复:Projects/ProjectDetail/Ideas/Settings)
const { confirmState, confirmDialog, answerConfirm } = useConfirm()

type FilterKey = 'all' | 'hot' | 'pending' | 'promoted'

// ⑤ 列表筛选/排序/分页状态持久化 localStorage(对齐 Tasks.vue:193-201 用 usePersistedRef),
// key 前缀 'ideas.',刷新页面/重开恢复用户的筛选视图。selectedId 不持久化(随路由恢复)。
const activeFilter = usePersistedRef<FilterKey>('ideas.activeFilter', 'all')
const selectedId = ref<string | null>(null)
const searchQuery = ref('')
// 列表排序:score 高分在前 / time 新在前(默认 score,避免高分灵感被淹没)
const sortMode = usePersistedRef<'score' | 'time'>('ideas.sortMode', 'score')

// 分页(F-260621-02 P3):pageSize=0 → 全量(向后兼容,等价改造前);用户选 N → 客户端切片
const page = usePersistedRef<number>('ideas.page', 1)
const pageSize = usePersistedRef<number>('ideas.pageSize', 0)

// ── 新建灵感模态框 ──
const showCaptureModal = ref(false)
const newIdeaTitle = ref('')
const newIdeaDesc = ref('')
const newIdeaTags = ref('')          // 逗号分隔输入(对标 KnowledgeDetail.vue tagsInput)
const newIdeaPriority = ref(2)       // 默认 medium,对标 CreateIdeaInput 0-3
const newIdeaSource = ref('')

// ── 异步按钮禁用态(防双击重复提交,对齐 ProviderPanel.vue saving ref) ──
const creating = ref(false)
const deleting = ref(false)
const promoting = ref(false)

const filters: { key: FilterKey; labelKey: string; icon: string }[] = [
  { key: 'all', labelKey: 'ideas.filter.all', icon: '📋' },
  { key: 'hot', labelKey: 'ideas.filter.hot', icon: '🔥' },
  { key: 'pending', labelKey: 'ideas.filter.pending', icon: '⏳' },
  { key: 'promoted', labelKey: 'ideas.filter.promoted', icon: '🚀' },
]

// ── 状态映射(单一数据源,列表/详情/下拉共用) ──
const statusOptions: { value: IdeaStatus; labelKey: string }[] = [
  { value: 'draft', labelKey: 'ideas.status.draft' },
  { value: 'pending_review', labelKey: 'ideas.status.pending_review' },
  { value: 'approved', labelKey: 'ideas.status.approved' },
  { value: 'promoted', labelKey: 'ideas.status.promoted' },
  { value: 'rejected', labelKey: 'ideas.status.rejected' },
]

// 任意 status 字符串 → 对应 i18n key;未知状态回退到原值显示
function statusLabelKey(status: IdeaStatus): string {
  return statusOptions.find(s => s.value === status)?.labelKey ?? status
}

// ── 后端查询构造(F-260621-02:status/keyword/order_by 下沉后端 WHERE) ──
//
// status 下沉:单一状态(all→不限 / promoted→promoted)走后端精确匹配;
// hot(按 score≥80)与 pending(多状态 draft+pending_review)无法映射单一后端 status,
// 仍在前端 filter(轻量,数据量小;后端 status 仅单值,扩多值属过度设计)。
// keyword/title+description LIKE、order_by(排序)全下沉后端,避免前端全表扫描/重排。
function buildIdeaQuery(): IdeaQuery {
  const q: IdeaQuery = {}
  // 排序下沉后端(score/time)
  q.order_by = sortMode.value === 'score' ? 'score' : 'created_at'
  // keyword 下沉后端(title/description LIKE)
  if (searchQuery.value.trim()) {
    q.keyword = searchQuery.value.trim()
  }
  // 单一状态映射:promoted → status=promoted;all/hot/pending 不走单一 status
  if (activeFilter.value === 'promoted') {
    q.status = 'promoted'
  }
  return q
}

// 按当前筛选/搜索/排序触发后端加载(防抖仅对 keyword 输入,筛选/排序即时)。
// 让 store.loading 驱动「加载中」空态显示(对齐 Tasks.vue 三态)。
let keywordDebounce: ReturnType<typeof setTimeout> | null = null
async function reloadIdeas(immediate = false) {
  if (keywordDebounce) {
    clearTimeout(keywordDebounce)
    keywordDebounce = null
  }
  const run = () => store.loadIdeas(buildIdeaQuery())
  if (immediate) {
    await run()
  } else {
    keywordDebounce = setTimeout(() => { void run() }, 300)
  }
}

// 筛选/排序变化即时重载;keyword 输入防抖重载
watch(activeFilter, () => { page.value = 1; void reloadIdeas(true) })
watch(sortMode, () => { page.value = 1; void reloadIdeas(true) })
watch(searchQuery, () => { page.value = 1; void reloadIdeas(false) })

const filteredIdeas = computed(() => {
  let ideas = store.ideas

  // hot(按 score≥80)/pending(多状态 draft+pending_review)保留前端 filter:
  // 后端 status 仅单值,无法表达 OR,扩多值属过度设计;数据量小,前端 filter 轻量。
  switch (activeFilter.value) {
    case 'hot': ideas = ideas.filter(i => (i.score ?? 0) >= 80); break
    case 'pending': ideas = ideas.filter(i => i.status === 'pending_review' || i.status === 'draft'); break
    default: break // all / promoted:后端已过滤,前端不再 filter
  }

  // 排序与 keyword 已下沉后端(buildIdeaQuery),前端不再重排/重过滤。
  return ideas
})

// 分页视图(F-260621-02 P3):pageSize=0 → 全量(等价改造前);否则取当前页窗口。
const pagedIdeas = computed(() => {
  if (pageSize.value <= 0) return filteredIdeas.value
  const start = (page.value - 1) * pageSize.value
  return filteredIdeas.value.slice(start, start + pageSize.value)
})

const currentIdea = computed(() => {
  if (!selectedId.value) return null
  return store.ideas.find(i => i.id === selectedId.value) ?? null
})

// ⑥ 选中态保留:分页启用时,选中灵感可能落在当前页窗口外(切筛选/排序/页码后),
// 右侧详情仍显示(currentIdea 从 store.ideas 全量查),但列表不滚动到它 — 视觉上「丢失」。
// 这里在筛选/数据变化后,若选中项仍在过滤结果中,自动跳到它所在页,保持选中可见。
watch([filteredIdeas, () => selectedId.value], () => {
  if (pageSize.value <= 0 || !selectedId.value) return
  const idx = filteredIdeas.value.findIndex(i => i.id === selectedId.value)
  if (idx < 0) return // 不在当前筛选结果中(被过滤),不强制跳页,保留详情面板显示
  const targetPage = Math.floor(idx / pageSize.value) + 1
  if (targetPage !== page.value) page.value = targetPage
})

// B-260615-25:灵感描述 Markdown 渲染已下沉至 IdeaDetail 子组件(共享模块单例渲染器)

// 评分档位 class(高/中/低 三色标),阈值统一走 scoreTier(单一来源,消除 4 处重复)
function scoreClass(score: number | null) {
  return 'score-' + scoreTier(score)
}

// formatDate 由 ../utils/time 提供（统一毫秒字符串解析，根治 Invalid Date）

function openCaptureModal() {
  newIdeaTitle.value = ''
  newIdeaDesc.value = ''
  newIdeaTags.value = ''
  newIdeaPriority.value = 2
  newIdeaSource.value = ''
  showCaptureModal.value = true
}

async function confirmCapture() {
  if (!newIdeaTitle.value.trim() || creating.value) return
  creating.value = true
  try {
    // tags 逗号分隔 → JSON 字符串(对标 KnowledgeDetail.vue saveEdit split+trim+filter 模式)
    const tags = newIdeaTags.value.split(',').map(t => t.trim()).filter(Boolean)
    await store.createIdea({
      title: newIdeaTitle.value.trim(),
      description: newIdeaDesc.value.trim() || undefined,
      priority: newIdeaPriority.value,
      tags: JSON.stringify(tags),
      source: newIdeaSource.value.trim() || undefined,
    })
    showCaptureModal.value = false
  } finally {
    creating.value = false
  }
}

async function deleteCurrentIdea() {
  if (!currentIdea.value || deleting.value) return
  if (!await confirmDialog(t('ideas.confirmDelete', { title: currentIdea.value.title }))) return
  deleting.value = true
  try {
    await store.deleteIdea(currentIdea.value.id)
    selectedId.value = null
  } finally {
    deleting.value = false
  }
}

async function promoteToProject() {
  if (!currentIdea.value || promoting.value) return
  promoting.value = true
  try {
    const res = await store.promoteIdea(currentIdea.value.id)
    router.push(`/projects/${res.project_id}`)
  } catch (e: any) {
    const msg = e?.toString() ?? t('ideas.promoteFailed')
    console.error(t('ideas.promoteFailed'), e)
    Message.error(msg)
  } finally {
    promoting.value = false
  }
}

async function refresh() {
  await store.loadIdeas(buildIdeaQuery())
}

const evaluating = ref(false)
const evalError = ref('')

async function evaluateCurrentIdea() {
  if (!currentIdea.value || evaluating.value) return

  evaluating.value = true
  evalError.value = ''
  try {
    await store.evaluateIdea(currentIdea.value.id)
  } catch (e: any) {
    evalError.value = e?.toString() ?? t('ideas.evalFailed')
    console.error(t('ideas.evalFailed'), e)
  } finally {
    evaluating.value = false
  }
}

async function onStatusChange(newStatus: IdeaStatus) {
  if (!currentIdea.value) return
  // ⑥ 状态切换确认:落到 promoted/rejected/archived 等终态(或离开 approved 失去立项入口)
  // 需用户确认,避免误点。中性流转(draft↔pending_review↔approved)直接落库。
  const from = currentIdea.value.status
  const needsConfirm = newStatus === 'promoted' || newStatus === 'rejected' || newStatus === 'archived'
    || (from === 'approved' && newStatus !== 'approved')
  if (needsConfirm) {
    const msg = t('ideas.confirmStatus', {
      title: currentIdea.value.title,
      from: t(statusOptions.find(s => s.value === from)?.labelKey ?? from),
      to: t(statusOptions.find(s => s.value === newStatus)?.labelKey ?? newStatus),
    })
    if (!await confirmDialog(msg, t('common.confirm'))) return
  }
  await store.updateIdea(currentIdea.value.id, 'status', newStatus)
}

// 接收 IdeaDetail 子组件 emit 的 'update-desc'(描述编辑保存)
async function onUpdateDesc(desc: string) {
  if (!currentIdea.value) return
  await store.updateIdea(currentIdea.value.id, 'description', desc)
}

// 接收 IdeaDetail 子组件 emit 的 'update-related'(关联灵感编辑保存,双向同步)
async function onUpdateRelated(ids: string[]) {
  if (!currentIdea.value) return
  await store.relateIdeas(currentIdea.value.id, ids)
}

onMounted(async () => {
  await store.loadIdeas(buildIdeaQuery())
  // 从路由参数恢复选中灵感（修复 /ideas/:id 直接访问空白页 B-260615-36）
  if (route.params.id) {
    const id = route.params.id as string
    const exists = store.ideas.some(i => i.id === id)
    if (!exists) {
      Message.warning(t('ideas.notFound'))
    }
    selectedId.value = id
  }
})

// 同组件内路由变化时同步 selectedId（列表点击跳 /ideas/:id）
watch(() => route.params.id, (id) => {
  if (id) {
    const ideaId = id as string
    const exists = store.ideas.some(i => i.id === ideaId)
    if (!exists) {
      Message.warning(t('ideas.notFound'))
    }
    selectedId.value = ideaId
  }
})
</script>

<style scoped>
.ideas { padding: 16px 20px 20px; }

/* page-header / btn / modal / filter-bar / filter-btn / search-box / empty-state 系列已提取到 global.css 全局 */

/* 排序按钮组(与状态筛选按钮视觉分隔) */
.sort-group {
  display: flex;
  gap: 4px;
  margin-left: auto;
}

/* ===== 两栏布局 ===== */
.ideas-layout {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: var(--df-gap-grid);
}

/* ===== 左侧列表 ===== */
.idea-list-panel {
  background: var(--df-bg-card);
  border: 0.5px solid var(--df-border);
  border-radius: var(--df-radius-lg);
  padding: 6px;
  max-height: calc(100vh - 200px);
  overflow-y: auto;
}
.idea-card {
  padding: 14px;
  border-radius: var(--df-radius);
  cursor: pointer;
  transition: all 0.15s;
  margin-bottom: 4px;
}
.idea-card:hover { background: rgba(108, 99, 255, 0.06); }
.idea-card.selected { background: rgba(108, 99, 255, 0.12); border: 0.5px solid var(--df-accent); }

.idea-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}
.idea-title { font-size: 14px; font-weight: 500; color: var(--df-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.idea-score {
  font-size: 13px; font-weight: 500;
  min-width: 32px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--df-radius-sm);
}
.score-high { background: rgba(100,255,218,0.15); color: var(--df-success); }
.score-mid { background: rgba(255,217,61,0.15); color: var(--df-warning); }
.score-low { background: rgba(255,107,107,0.15); color: var(--df-danger); }

.idea-desc-preview { font-size: 12px; color: var(--df-text-dim); margin-bottom: 8px; line-height: 1.4; }

.idea-card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.idea-date { font-size: 11px; color: var(--df-text-dim); }

/* ===== 状态标签已提取到 styles/components.css 全局(.status-tag 系列) ===== */

/* ===== 右侧详情(详情内容由 IdeaDetail 子组件渲染,父级仅保留未选中空态壳) ===== */
.idea-detail-panel {
  background: var(--df-bg-card);
  border: 0.5px solid var(--df-border);
  border-radius: var(--df-radius-lg);
  padding: var(--df-pad-panel);
  max-height: calc(100vh - 200px);
  overflow-y: auto;
}
.idea-empty {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* empty-state / empty-icon 已提取到 global.css 全局 */

/* ===== 响应式 ===== */
@media (max-width: 768px) {
  .ideas { padding: 16px; }
  .ideas-layout {
    grid-template-columns: 1fr;
  }
  .search-box {
    max-width: 100%;
    order: -1;
    width: 100%;
    margin-bottom: 8px;
  }
}

/* ===== 模态框字段样式(modal-overlay/box/field/actions 已提取到 global.css) ===== */
/* Ideas 模态的 select 用 .modal-field select 全局覆盖,无需额外 scoped */
</style>
