<template>
  <div class="materials-page">
    <section class="materials-hero">
      <div>
        <span class="eyebrow">我的素材库</span>
        <h1>沉淀教材、课件、试题和课堂资料</h1>
        <p>上传解析后的材料会自动保存，可按学科、类型和关键词检索，并一键带入课件、组题、教案、命题或数据回收。</p>
      </div>
      <div class="hero-actions">
        <button class="upload-btn secondary" type="button" :disabled="uploading" @click="pickFile('image')">
          <el-icon><Camera /></el-icon>
          {{ uploadingMode === 'image' ? '识别中' : '拍照/图片' }}
        </button>
        <button class="upload-btn" type="button" :disabled="uploading" @click="pickFile('file')">
          <el-icon><Upload /></el-icon>
          {{ uploadingMode === 'file' ? '解析中' : '上传解析' }}
        </button>
      </div>
      <input ref="fileInputRef" type="file" class="hidden-input" :accept="uploadAccept" @change="handleFileChange" />
    </section>

    <section class="filter-panel">
      <div class="segmented">
        <button
          v-for="type in materialTypes"
          :key="type.value"
          type="button"
          :class="{ active: filters.material_type === type.value }"
          @click="setType(type.value)"
        >
          {{ type.label }}
        </button>
      </div>
      <div class="filter-line">
        <el-select v-model="filters.subject" placeholder="全部学科" clearable @change="loadData" style="width: 150px">
          <el-option v-for="s in subjects" :key="s" :label="s" :value="s" />
        </el-select>
        <div class="search-box">
          <el-icon><Search /></el-icon>
          <input v-model="filters.keyword" placeholder="搜索素材标题、文件名或正文摘要" @keyup.enter="loadData" />
          <button v-if="filters.keyword" type="button" @click="clearKeyword">清除</button>
        </div>
      </div>
    </section>

    <section class="material-grid" v-loading="loading">
      <article v-for="item in materials" :key="item.id" class="material-card">
        <div class="material-cover" :class="coverClass(item)">
          <span>{{ typeLabel(item.material_type) }}</span>
          <strong>{{ item.title }}</strong>
          <em>{{ item.subject || '通用' }} · {{ item.grade || formatFileSize(item.size) }}</em>
        </div>
        <div class="material-body">
          <div class="material-title-row">
            <h3>{{ item.title }}</h3>
            <el-dropdown trigger="click" @command="(cmd: string) => reuseMaterial(item, cmd)">
              <button class="more-btn" type="button"><el-icon><MoreFilled /></el-icon></button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="courseware">生成课件</el-dropdown-item>
                  <el-dropdown-item command="animation">生成动画</el-dropdown-item>
                  <el-dropdown-item command="exercise">生成练习</el-dropdown-item>
                  <el-dropdown-item command="lesson">生成教案</el-dropdown-item>
                  <el-dropdown-item command="exam">智能命题</el-dropdown-item>
                  <el-dropdown-item command="classroom">数据回收</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
          <p>{{ item.summary || '暂无摘要' }}</p>
          <div class="material-meta">
            <span>{{ item.filename }}</span>
            <span>{{ formatCount(item.char_count) }}字</span>
          </div>
          <div class="tag-line" v-if="item.tags?.length">
            <el-tag v-for="tag in item.tags" :key="tag" size="small" effect="plain">{{ tag }}</el-tag>
          </div>
          <div class="card-actions">
            <button type="button" @click="openEdit(item)">编辑</button>
            <button type="button" class="primary" @click="reuseMaterial(item, 'courseware')">带入课件</button>
            <button type="button" @click="reuseMaterial(item, 'animation')">生成动画</button>
            <el-popconfirm title="确定删除这个素材？" @confirm="removeMaterial(item.id)">
              <template #reference>
                <button type="button" class="danger">删除</button>
              </template>
            </el-popconfirm>
          </div>
        </div>
      </article>
    </section>

    <div v-if="!loading && materials.length === 0" class="empty-state">
      <el-icon><FolderOpened /></el-icon>
      <strong>还没有素材</strong>
      <span>上传教材、课件、试题或图片，解析后会自动进入素材库。</span>
      <button type="button" @click="pickFile('file')">上传第一个素材</button>
    </div>

    <el-dialog v-model="showEdit" title="编辑素材信息" width="640px" :close-on-click-modal="false">
      <el-form :model="editForm" label-position="top" class="edit-form">
        <el-form-item label="素材标题">
          <el-input v-model="editForm.title" />
        </el-form-item>
        <div class="edit-grid">
          <el-form-item label="学科">
            <el-select v-model="editForm.subject" filterable allow-create clearable style="width: 100%">
              <el-option v-for="s in subjects" :key="s" :label="s" :value="s" />
            </el-select>
          </el-form-item>
          <el-form-item label="年级">
            <el-input v-model="editForm.grade" placeholder="例如：六年级下册" />
          </el-form-item>
        </div>
        <el-form-item label="标签">
          <el-select v-model="editForm.tags" multiple filterable allow-create placeholder="输入标签后回车" style="width: 100%" />
        </el-form-item>
        <el-form-item label="摘要">
          <el-input v-model="editForm.summary" type="textarea" :rows="8" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showEdit = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="saveEdit">保存修改</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { parseMaterial } from '@/api/ai'
import { deleteMaterial, getMaterials, updateMaterial } from '@/api/material'
import { useUserStore } from '@/stores/user'

const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const fileInputRef = ref<HTMLInputElement>()
const uploadAccept = ref('.txt,.md,.csv,.json,.docx,.pptx,.pdf,.xlsx,image/*')
const uploadMode = ref<'file' | 'image'>('file')
const uploadingMode = ref<'file' | 'image' | ''>('')
const loading = ref(false)
const uploading = ref(false)
const saving = ref(false)
const showEdit = ref(false)
const materials = ref<any[]>([])
const subjects = ['语文', '数学', '英语', '物理', '化学', '生物', '历史', '地理', '信息科技', '课堂工具']
const materialTypes = [
  { value: '', label: '全部' },
  { value: 'txt', label: '文本' },
  { value: 'docx', label: 'Word' },
  { value: 'pptx', label: 'PPT' },
  { value: 'image', label: '图片' },
  { value: 'csv', label: '表格' },
  { value: 'json', label: '结构化' },
]
const filters = reactive({ material_type: '', subject: '', keyword: '' })
const editForm = reactive({
  id: 0,
  title: '',
  subject: '',
  grade: '',
  tags: [] as string[],
  summary: '',
})

onMounted(() => {
  filters.keyword = typeof route.query.keyword === 'string' ? route.query.keyword : ''
  loadData()
})

watch(() => route.query.keyword, (keyword) => {
  filters.keyword = typeof keyword === 'string' ? keyword : ''
  loadData()
})

function setType(type: string) {
  filters.material_type = type
  loadData()
}

function clearKeyword() {
  filters.keyword = ''
  loadData()
}

async function loadData() {
  if (!ensureLoggedIn(false)) return
  loading.value = true
  try {
    const data: any = await getMaterials({
      material_type: filters.material_type || undefined,
      subject: filters.subject || undefined,
      keyword: filters.keyword || undefined,
      limit: 100,
    })
    materials.value = Array.isArray(data?.data) ? data.data : Array.isArray(data) ? data : []
  } finally {
    loading.value = false
  }
}

function pickFile(type: 'file' | 'image') {
  if (!ensureLoggedIn(true)) return
  uploadMode.value = type
  uploadAccept.value = type === 'image' ? 'image/*' : '.txt,.md,.csv,.json,.docx,.pptx,.pdf,.xlsx,image/*'
  if (fileInputRef.value) {
    if (type === 'image') fileInputRef.value.setAttribute('capture', 'environment')
    else fileInputRef.value.removeAttribute('capture')
  }
  fileInputRef.value?.click()
}

async function handleFileChange(event: Event) {
  const file = (event.target as HTMLInputElement).files?.[0]
  if (!file) return
  uploading.value = true
  uploadingMode.value = uploadMode.value
  try {
    const parsed: any = await parseMaterial(file)
    userStore.refreshCreditsFromResponse(parsed)
    const data = parsed.data || parsed
    ElMessage.success(data.material_type === 'image' ? '图片素材已保存，可带入生成' : '素材已解析并保存')
    await loadData()
  } finally {
    uploading.value = false
    uploadingMode.value = ''
    ;(event.target as HTMLInputElement).value = ''
  }
}

function openEdit(item: any) {
  editForm.id = item.id
  editForm.title = item.title || item.filename || ''
  editForm.subject = item.subject || ''
  editForm.grade = item.grade || ''
  editForm.tags = Array.isArray(item.tags) ? [...item.tags] : []
  editForm.summary = item.summary || ''
  showEdit.value = true
}

async function saveEdit() {
  if (!editForm.id) return
  saving.value = true
  try {
    await updateMaterial(editForm.id, {
      title: editForm.title,
      subject: editForm.subject,
      grade: editForm.grade,
      tags: editForm.tags,
      summary: editForm.summary,
    })
    ElMessage.success('素材已更新')
    showEdit.value = false
    await loadData()
  } finally {
    saving.value = false
  }
}

async function removeMaterial(id: number) {
  await deleteMaterial(id)
  ElMessage.success('素材已删除')
  await loadData()
}

function reuseMaterial(item: any, mode: string) {
  const prompt = buildPrompt(item, mode)
  localStorage.setItem('quick_create_prompt', prompt)
  if (mode === 'exam') router.push('/exam')
  else if (mode === 'exercise') router.push('/exercise')
  else if (mode === 'lesson') router.push('/lesson-plan')
  else if (mode === 'animation') router.push('/animation')
  else if (mode === 'classroom') router.push('/classroom')
  else router.push('/courseware/create')
}

function buildPrompt(item: any, mode: string) {
  const imageHint = item.material_type === 'image'
    ? '\n\n【图片使用要求】\n这是一份拍照/图片素材，请优先围绕图片中的教材页、题目、板书、图表或课堂场景设计内容；如果图片文字未完全识别，请保留“请教师补充图片关键文字”的提示位。'
    : ''
  const base = `请基于素材《${item.title || item.filename}》进行教学创作。\n\n【素材摘要】\n${item.summary || '暂无摘要，请结合素材标题和类型进行创作。'}${imageHint}`
  if (mode === 'exam') return `${base}\n\n请据此生成一套原创试题，覆盖核心知识点，附答案和解析。`
  if (mode === 'exercise') return `${base}\n\n请据此生成可课堂互动的练习/教学游戏，题目有梯度并附解析。`
  if (mode === 'lesson') return `${base}\n\n请据此生成结构化大单元教案，包含目标、重难点、活动、评价和作业。`
  if (mode === 'animation') return `${base}\n\n请据此生成一个课堂教学动画，突出知识形成过程、关键变化和可观察的步骤标注。`
  if (mode === 'classroom') return `${base}\n\n请据此设计一个课堂数据回收活动，用于收集学生理解、选择或反馈。`
  return `${base}\n\n请据此生成专业级互动课件，包含导入、讲解、互动练习和课堂总结。`
}

function ensureLoggedIn(redirect: boolean) {
  if (localStorage.getItem('access_token')) return true
  ElMessage.warning('请先登录后使用素材库')
  if (redirect) router.push({ path: '/login', query: { redirect: '/materials' } })
  return false
}

function typeLabel(type: string) {
  const map: Record<string, string> = {
    docx: 'Word',
    pptx: 'PPT',
    csv: '表格',
    json: '结构化',
    md: 'Markdown',
    txt: '文本',
    text: '文本',
    image: '图片',
  }
  return map[type] || '素材'
}

function coverClass(item: any) {
  if (item.material_type === 'image') return 'cover-mint'
  if (item.material_type === 'pptx') return 'cover-blue'
  if (item.material_type === 'docx') return 'cover-green'
  if (item.material_type === 'csv' || item.material_type === 'json') return 'cover-yellow'
  return 'cover-cream'
}

function formatFileSize(size: number) {
  const n = Number(size || 0)
  if (n < 1024) return `${n}B`
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`
  return `${(n / 1024 / 1024).toFixed(1)}MB`
}

function formatCount(value: number) {
  const n = Number(value || 0)
  if (n >= 10000) return `${(n / 10000).toFixed(1)}万`
  return String(n)
}
</script>

<style scoped>
.materials-page { min-height: 100vh; background: #f7faf6; padding: 26px 36px 40px; color: #173f35; }
.materials-hero { max-width: 1280px; margin: 0 auto 18px; display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; border: 1px solid #dce8de; border-radius: 14px; background: #fff; padding: 24px; }
.eyebrow { color: #00724f; font-size: 13px; font-weight: 900; }
.materials-hero h1 { margin: 8px 0 8px; color: #173f35; font-size: 28px; line-height: 1.2; }
.materials-hero p { max-width: 760px; color: #6a7f77; line-height: 1.7; }
.hero-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.upload-btn { height: 38px; display: inline-flex; align-items: center; gap: 7px; border: none; border-radius: 19px; background: #00543d; color: #fff; padding: 0 18px; font-weight: 900; cursor: pointer; white-space: nowrap; }
.upload-btn.secondary { border: 1px solid #9ed0aa; background: #eaf7e9; color: #00543d; }
.upload-btn:disabled { opacity: .62; cursor: not-allowed; }
.hidden-input { display: none; }
.filter-panel { max-width: 1280px; margin: 0 auto 18px; border: 1px solid #dce8de; border-radius: 14px; background: #fff; padding: 14px; }
.segmented { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.segmented button { height: 32px; border: 1px solid #dbe8de; border-radius: 16px; background: #fff; color: #51665f; padding: 0 13px; cursor: pointer; }
.segmented button.active, .segmented button:hover { border-color: #9ed0aa; background: #eaf7e9; color: #00543d; font-weight: 900; }
.filter-line { display: flex; align-items: center; gap: 10px; }
.search-box { height: 34px; flex: 1; min-width: 220px; display: flex; align-items: center; gap: 8px; border: 1px solid #dbe8de; border-radius: 17px; padding: 0 10px; background: #f8faf8; }
.search-box input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; color: #173f35; }
.search-box button { border: none; background: transparent; color: #00724f; cursor: pointer; font-weight: 800; }
.material-grid { max-width: 1280px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.material-card { overflow: hidden; border: 1px solid #dce8de; border-radius: 14px; background: #fff; }
.material-cover { min-height: 148px; display: flex; flex-direction: column; justify-content: flex-end; padding: 18px; }
.material-cover span { width: fit-content; border-radius: 999px; background: rgba(255,255,255,.86); color: #00543d; padding: 4px 10px; font-size: 12px; font-weight: 900; }
.material-cover strong { margin-top: 12px; color: #173f35; font-size: 19px; line-height: 1.25; }
.material-cover em { margin-top: 7px; color: #51665f; font-style: normal; font-size: 13px; }
.cover-green { background: linear-gradient(135deg, #dff7e5, #9ed0aa); }
.cover-blue { background: linear-gradient(135deg, #dbe8ff, #a8c7ff); }
.cover-mint { background: linear-gradient(135deg, #d7f8ef, #8be1c6); }
.cover-yellow { background: linear-gradient(135deg, #fff1a1, #ffd84d); }
.cover-cream { background: linear-gradient(135deg, #f6edd3, #e6d0a3); }
.material-body { padding: 16px; }
.material-title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.material-title-row h3 { color: #173f35; font-size: 16px; line-height: 1.35; }
.more-btn { width: 30px; height: 30px; border: 1px solid #dbe8de; border-radius: 8px; background: #fff; color: #31584d; cursor: pointer; }
.material-body p { height: 86px; margin-top: 8px; color: #6a7f77; font-size: 13px; line-height: 1.6; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.material-meta { margin-top: 12px; display: flex; justify-content: space-between; gap: 10px; color: #87958f; font-size: 12px; }
.material-meta span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-line { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.card-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 14px; }
.card-actions button { height: 32px; border: 1px solid #dbe8de; border-radius: 8px; background: #fff; color: #31584d; font-weight: 900; cursor: pointer; }
.card-actions button.primary { border-color: #00543d; background: #00543d; color: #fff; }
.card-actions button.danger { color: #b42318; }
.empty-state { max-width: 1280px; min-height: 320px; margin: 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; border: 1px dashed #cfe0d3; border-radius: 14px; background: #fff; color: #75867f; }
.empty-state .el-icon { font-size: 40px; color: #9aaba4; }
.empty-state strong { color: #173f35; }
.empty-state button { border: none; border-radius: 18px; background: #00543d; color: #fff; padding: 8px 18px; font-weight: 900; cursor: pointer; }
.edit-grid { display: grid; grid-template-columns: repeat(2, minmax(180px, 1fr)); gap: 0 14px; }
@media (max-width: 760px) {
  .materials-page { padding: 16px; }
  .materials-hero { align-items: flex-start; flex-direction: column; }
  .hero-actions { width: 100%; justify-content: flex-start; }
  .filter-line { align-items: stretch; flex-direction: column; }
  .search-box { width: 100%; }
  .card-actions { grid-template-columns: repeat(2, 1fr); }
  .edit-grid { grid-template-columns: 1fr; }
}
</style>
