<template>
  <div class="list-page">
    <div class="page-title">材料管理</div>
    <div class="toolbar">
      <div class="toolbar-row">
        <el-input v-model="filters.name" placeholder="材料名称" clearable style="width: 180px" @keyup.enter="triggerSearch" />
        <el-select v-model="filters.status" placeholder="状态" clearable style="width: 140px" @change="triggerSearch">
          <el-option v-for="item in statusOptions" :key="item[0]" :label="item[1]" :value="item[0]" />
        </el-select>
        <el-input v-model="filters.material_category" placeholder="细分种类" clearable style="width: 160px" @keyup.enter="triggerSearch" />
        <el-select v-model="filters.material_subcategory" placeholder="材料子类" clearable style="width: 160px" @change="triggerSearch">
          <el-option v-for="item in filterSubcategoryOptions" :key="item.value" :label="item.name" :value="item.value" />
        </el-select>
        <el-select
          v-model="filters.brand"
          placeholder="品牌"
          clearable
          filterable
          remote
          :remote-method="searchBrands"
          :loading="brandSearchLoading"
          style="width: 160px"
          @change="triggerSearch"
        >
          <el-option v-for="item in brandFilterOptions" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
        <el-badge :is-dot="hasAdvancedActive" class="advanced-badge">
          <el-button text @click="advancedOpen = !advancedOpen">
            高级筛选 {{ advancedOpen ? '▲' : '▼' }}
          </el-button>
        </el-badge>

        <div class="toolbar-spacer" />

        <el-button v-if="isAdmin" :loading="importing" @click="importDialogVisible = true">
          {{ importing ? '导入中...' : '导入数据' }}
        </el-button>
        <el-button :loading="exporting" @click="handleExportExcel">
          {{ exporting ? '导出中...' : '导出' }}
        </el-button>
        <el-button type="primary" @click="openCreate">新增材料</el-button>

        <el-popover placement="bottom-end" :width="460" trigger="click">
          <template #reference>
            <el-button title="列设置">⚙ 列</el-button>
          </template>
          <div class="column-setting">
            <div v-for="group in COLUMN_GROUPS" :key="group.key" class="column-setting__group">
              <div class="column-setting__header">
                <span class="column-setting__title">{{ group.label }}</span>
                <el-button size="small" text @click="setGroupVisible(groupColumnKeys(group.key), true)">全选</el-button>
                <el-button size="small" text @click="setGroupVisible(groupColumnKeys(group.key), false)">全不选</el-button>
              </div>
              <div class="column-setting__cols">
                <el-checkbox
                  v-for="col in columnsOfGroup(group.key)"
                  :key="col.key"
                  :model-value="isVisible(col.key)"
                  @change="toggle(col.key)"
                >{{ col.label }}</el-checkbox>
              </div>
            </div>
            <div class="column-setting__footer">
              <el-button size="small" @click="resetColumns">恢复默认</el-button>
            </div>
          </div>
        </el-popover>
      </div>

      <div v-show="advancedOpen" class="toolbar-row toolbar-row--advanced">
        <el-select v-model="filters.major_category" placeholder="材料大类" clearable style="width: 140px" @change="triggerSearch">
          <el-option v-for="item in majorCategoryOptions" :key="item[0]" :label="item[1]" :value="item[0]" />
        </el-select>
        <el-select v-model="filters.stage" placeholder="阶段" clearable style="width: 140px" @change="triggerSearch">
          <el-option v-for="item in stageOptions" :key="item[0]" :label="item[1]" :value="item[0]" />
        </el-select>
        <el-select v-model="filters.importance_level" placeholder="重要等级" clearable style="width: 140px" @change="triggerSearch">
          <el-option v-for="item in importanceLevelOptions" :key="item[0]" :label="item[1]" :value="item[0]" />
        </el-select>
        <el-select v-model="filters.factory__cooperation_mode" placeholder="合作模式" clearable style="width: 140px" @change="triggerSearch">
          <el-option v-for="item in cooperationModeOptions" :key="item[0]" :label="item[1]" :value="item[0]" />
        </el-select>
        <el-select
          v-model="filters.factory"
          placeholder="供应商"
          clearable
          filterable
          remote
          :remote-method="searchFactories"
          :loading="factorySearchLoading"
          style="width: 180px"
          @change="triggerSearch"
        >
          <el-option v-for="item in factoryFilterOptions" :key="item.id" :label="item.short_name || item.factory_name" :value="item.id" />
        </el-select>
        <el-input v-model="filters.landing_project" placeholder="落地项目" clearable style="width: 160px" @keyup.enter="triggerSearch" />
        <el-input v-model="filters.contact_person" placeholder="对接人" clearable style="width: 120px" @keyup.enter="triggerSearch" />
        <el-input v-model="filters.handler" placeholder="经办人" clearable style="width: 120px" @keyup.enter="triggerSearch" />
        <el-input-number v-model="filters.cost_compare__gte" :min="0" placeholder="成本≥" controls-position="right" style="width: 130px" @change="triggerSearch" />
        <el-input-number v-model="filters.cost_compare__lte" :min="0" placeholder="成本≤" controls-position="right" style="width: 130px" @change="triggerSearch" />
        <el-select v-model="filters.score_level__gte" placeholder="综合评分≥" clearable style="width: 140px" @change="triggerSearch">
          <el-option v-for="n in [1, 2, 3]" :key="n" :label="`${n} 星及以上`" :value="n" />
        </el-select>
        <el-button @click="resetFilters">重置筛选</el-button>
      </div>
    </div>

    <div class="table-wrap">
      <el-table v-loading="tableLoading" :data="materials" border height="100%">
        <template v-for="group in COLUMN_GROUPS" :key="group.key">
          <el-table-column
            v-if="hasVisibleInGroup(group.key)"
            :label="group.label"
            align="center"
          >
            <el-table-column
              v-for="col in visibleColumnsOfGroup(group.key)"
              :key="col.key"
              :prop="col.slot || col.formatter ? undefined : col.key"
              :label="col.label"
              :min-width="col.minWidth"
              :width="col.width"
              :show-overflow-tooltip="col.showOverflowTooltip"
            >
              <template v-if="col.slot === 'tags'" #default="scope">
                <template v-if="Array.isArray(scope.row[col.key]) && scope.row[col.key].length">
                  <el-tag
                    v-for="(t, idx) in scope.row[col.key]"
                    :key="idx"
                    size="small"
                    style="margin-right: 4px; margin-bottom: 2px;"
                  >{{ displayTag(col.key, t) }}</el-tag>
                </template>
                <span v-else>-</span>
              </template>
              <template v-else-if="col.slot === 'stars'" #default="scope">
                <span v-if="scope.row[col.key]" class="stars">
                  <span v-for="n in Number(scope.row[col.key]) || 0" :key="n">★</span>
                </span>
                <span v-else>-</span>
              </template>
              <template v-else-if="col.formatter" #default="scope">
                {{ col.formatter(scope.row) }}
              </template>
            </el-table-column>
          </el-table-column>
        </template>

        <el-table-column label="操作" width="320" fixed="right">
          <template #default="scope">
            <div class="table-actions">
              <el-button size="small" @click="goDetail(scope.row)">详情</el-button>
              <el-button v-if="canEdit(scope.row)" size="small" @click="openEdit(scope.row)">编辑</el-button>
              <el-button v-if="canSubmit(scope.row)" size="small" type="warning" @click="onSubmitAudit(scope.row)">提交审核</el-button>
              <el-button v-if="canApprove(scope.row)" size="small" type="success" @click="onApprove(scope.row)">审核通过</el-button>
              <el-button v-if="canApprove(scope.row)" size="small" type="danger" @click="onReject(scope.row)">审核拒绝</el-button>
              <el-button v-if="canDelete(scope.row)" size="small" type="danger" @click="onDelete(scope.row)">删除</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="pagination">
      <el-pagination
        background
        layout="total, sizes, prev, pager, next, jumper"
        :page-sizes="[10, 20, 50]"
        :current-page="pagination.page"
        :page-size="pagination.pageSize"
        :total="pagination.total"
        @current-change="onPageChange"
        @size-change="onPageSizeChange"
      />
    </div>

    <el-drawer
      v-model="dialogVisible"
      :title="dialogTitle"
      size="60%"
      :close-on-click-modal="false"
      :destroy-on-close="true"
      class="material-drawer"
    >
      <MaterialForm ref="materialFormRef" v-model="form" mode="edit" />
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="onSave">保存</el-button>
      </template>
    </el-drawer>

    <el-dialog v-model="importDialogVisible" title="导入材料" width="420px">
      <div class="import-dialog">
        <div class="import-dialog__text">请先下载模板，按模板填写后上传 `.xlsx` 文件。</div>
        <div class="import-dialog__actions">
          <a :href="templateDownloadUrl" download="材料导入模板.xlsx">
            <el-button>模板下载</el-button>
          </a>
          <el-upload
            :auto-upload="true"
            :show-file-list="false"
            :http-request="handleImportExcel"
            accept=".xlsx"
          >
            <el-button type="primary" :loading="importing">{{ importing ? '导入中...' : '上传文件' }}</el-button>
          </el-upload>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useAuth } from '@/store/auth'
import {
  fetchMaterials,
  fetchMaterialDetail,
  createMaterial,
  updateMaterial,
  deleteMaterial,
  submitMaterial,
  approveMaterial,
  rejectMaterial,
  fetchMaterialChoices,
  importMaterialsExcel,
  exportMaterialsExcel
} from '@/api/material'
import { fetchSubcategories } from '@/api/category'
import { fetchBrands } from '@/api/brand'
import { fetchFactories } from '@/api/factory'
import MaterialForm from '@/views/material/MaterialForm.vue'
import { MATERIAL_COLUMNS, COLUMN_GROUPS } from '@/views/material/materialColumns'
import { useColumnPreferences } from '@/composables/useColumnPreferences'

const router = useRouter()
const { isAdmin } = useAuth()
const materials = ref([])
const tableLoading = ref(false)
const pagination = reactive({
  page: 1,
  pageSize: 20,
  total: 0
})
const dialogVisible = ref(false)
const importDialogVisible = ref(false)
const dialogTitle = ref('')
const isEdit = ref(false)
const currentId = ref(null)
const importing = ref(false)
const exporting = ref(false)
const materialFormRef = ref(null)
const templateDownloadUrl = `http://101.42.1.64:2260/media/material_import_template.xlsx`

const filters = reactive({
  // 常用
  name: '',
  status: '',
  material_subcategory: '',
  brand: '',
  // 高级
  major_category: '',
  material_category: '',
  stage: '',
  importance_level: '',
  factory: '',
  factory__cooperation_mode: '',
  landing_project: '',
  cost_compare__gte: null,
  cost_compare__lte: null,
  score_level__gte: null,
  contact_person: '',
  handler: '',
})

const advancedKeys = [
  'major_category', 'material_category', 'stage', 'importance_level',
  'factory', 'factory__cooperation_mode', 'landing_project',
  'cost_compare__gte', 'cost_compare__lte', 'score_level__gte',
  'contact_person', 'handler',
]
const advancedOpen = ref(false)
const hasAdvancedActive = computed(() =>
  advancedKeys.some((k) => {
    const v = filters[k]
    return v !== '' && v !== null && v !== undefined
  })
)

const brandFilterOptions = ref([])
const brandSearchLoading = ref(false)
const factoryFilterOptions = ref([])
const factorySearchLoading = ref(false)
const statusOptions = ref([])
const majorCategoryOptions = ref([])
const stageOptions = ref([])
const importanceLevelOptions = ref([])
const cooperationModeOptions = ref([])
const applicationSceneChoices = ref([])
const advantageChoices = ref([])
const filterSubcategoryOptions = ref([])

// 列显隐
const { isVisible, toggle, setGroupVisible, reset: resetColumns } = useColumnPreferences('mat3:material-list:columns:v1')
const columnsOfGroup = (groupKey) => MATERIAL_COLUMNS.filter((c) => c.group === groupKey)
const visibleColumnsOfGroup = (groupKey) => MATERIAL_COLUMNS.filter((c) => c.group === groupKey && isVisible(c.key))
const hasVisibleInGroup = (groupKey) => visibleColumnsOfGroup(groupKey).length > 0
const groupColumnKeys = (groupKey) => columnsOfGroup(groupKey).map((c) => c.key)

// tag 中文化映射
const displayTag = (colKey, code) => {
  const choices = colKey === 'application_scene' ? applicationSceneChoices.value
    : colKey === 'advantage' ? advantageChoices.value
    : []
  const hit = choices.find((c) => c[0] === code)
  return hit ? hit[1] : code
}

const emptyForm = () => ({
  name: '',
  major_category: '',
  material_category: '',
  material_subcategory: '',
  stage: '',
  importance_level: '',
  landing_project: '',
  contact_person: '',
  contact_phone: '',
  handler: '',
  remark: '',
  spec: '',
  standard: '',
  application_scene: [],
  application_desc: '',
  replace_type: '',
  advantage: [],
  advantage_desc: '',
  cost_compare: null,
  cost_desc: '',
  cases: '',
  brochure: null,
  brochure_url: '',
  quality_level: null,
  durability_level: null,
  eco_level: null,
  carbon_level: null,
  score_level: null,
  connection_method: '',
  construction_method: '',
  limit_condition: '',
  factory: null,
  brand: null
})

const form = ref(emptyForm())

const buildQueryParams = () => {
  const params = { page: pagination.page, page_size: pagination.pageSize }
  Object.entries(filters).forEach(([k, v]) => {
    if (v !== '' && v !== null && v !== undefined) params[k] = v
  })
  return params
}

const loadMaterials = async () => {
  tableLoading.value = true
  try {
    const data = await fetchMaterials(buildQueryParams())
    materials.value = data.results || data
    pagination.total = data.count || materials.value.length
  } finally {
    tableLoading.value = false
  }
}

const triggerSearch = () => {
  pagination.page = 1
  loadMaterials()
}

const resetFilters = () => {
  filters.name = ''
  filters.status = ''
  filters.material_subcategory = ''
  filters.brand = ''
  filters.major_category = ''
  filters.material_category = ''
  filters.stage = ''
  filters.importance_level = ''
  filters.factory = ''
  filters.factory__cooperation_mode = ''
  filters.landing_project = ''
  filters.cost_compare__gte = null
  filters.cost_compare__lte = null
  filters.score_level__gte = null
  filters.contact_person = ''
  filters.handler = ''
  triggerSearch()
}

const loadChoices = async () => {
  const data = await fetchMaterialChoices()
  statusOptions.value = data.status || []
  majorCategoryOptions.value = data.major_category || []
  stageOptions.value = data.stage || []
  importanceLevelOptions.value = data.importance_level || []
  cooperationModeOptions.value = data.cooperation_mode || []
  applicationSceneChoices.value = data.application_scene || []
  advantageChoices.value = data.advantage || []
}

const loadFilterSubcategories = async () => {
  const data = await fetchSubcategories({})
  filterSubcategoryOptions.value = (data.results || data).map((item) => ({
    id: item.id,
    name: item.name,
    value: item.value
  }))
}

const loadBrandFilterOptions = async () => {
  const data = await fetchBrands({ page_size: 100 })
  brandFilterOptions.value = data.results || data
}

const loadFactoryFilterOptions = async () => {
  const data = await fetchFactories({ page_size: 100 })
  factoryFilterOptions.value = data.results || data
}

const searchBrands = async (query) => {
  brandSearchLoading.value = true
  try {
    const data = await fetchBrands({ page_size: 50, search: query || '' })
    brandFilterOptions.value = data.results || data
  } finally {
    brandSearchLoading.value = false
  }
}

const searchFactories = async (query) => {
  factorySearchLoading.value = true
  try {
    const data = await fetchFactories({ page_size: 50, search: query || '' })
    factoryFilterOptions.value = data.results || data
  } finally {
    factorySearchLoading.value = false
  }
}

const openCreate = () => {
  form.value = emptyForm()
  isEdit.value = false
  dialogTitle.value = '新增材料'
  dialogVisible.value = true
}

const openEdit = async (row) => {
  isEdit.value = true
  currentId.value = row.id
  const item = await fetchMaterialDetail(row.id)
  form.value = {
    ...emptyForm(),
    ...item,
    application_scene: item.application_scene || [],
    advantage: item.advantage || [],
    brochure_url: item.brochure_url || '',
    brand: item.brand || null
  }
  dialogTitle.value = '编辑材料'
  dialogVisible.value = true
}

const onSave = async () => {
  if (!form.value.brand) {
    ElMessage.warning('请选择品牌')
    return
  }
  try {
    const payload = { ...form.value }
    delete payload.brochure_url
    delete payload.brand_name
    if (!isAdmin.value) {
      delete payload.factory
    }
    if (isEdit.value) {
      await updateMaterial(currentId.value, payload)
    } else {
      await createMaterial(payload)
      pagination.page = 1
    }
    ElMessage.success('保存成功')
    dialogVisible.value = false
    await loadMaterials()
  } catch (error) {
    ElMessage.error(error.response?.data?.detail || '保存失败')
  }
}

const handleImportExcel = async (options) => {
  importing.value = true
  try {
    const result = await importMaterialsExcel(options.file)
    pagination.page = 1
    await loadMaterials()
    importDialogVisible.value = false
    ElMessage.success(`导入完成：新增 ${result.created} 条，更新 ${result.updated} 条，跳过 ${result.skipped} 条，新建供应商 ${result.created_factory || 0} 条`)
  } catch (error) {
    ElMessage.error(error.response?.data?.detail || '导入失败')
  } finally {
    importing.value = false
  }
}

const getDownloadFilename = (headers, fallback) => {
  const disposition = headers?.['content-disposition'] || ''
  const utf8Match = disposition.match(/filename\*=UTF-8''([^;]+)/i)
  if (utf8Match?.[1]) {
    return decodeURIComponent(utf8Match[1])
  }
  const asciiMatch = disposition.match(/filename="?([^"]+)"?/i)
  if (asciiMatch?.[1]) {
    return asciiMatch[1]
  }
  return fallback
}

const handleExportExcel = async () => {
  exporting.value = true
  try {
    const response = await exportMaterialsExcel({ ...filters })
    const blob = response.data instanceof Blob ? response.data : new Blob([response.data])
    const filename = getDownloadFilename(response.headers, 'materials_export.xlsx')
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    ElMessage.success('导出成功')
  } catch (error) {
    let detail = error.response?.data?.detail
    if (error.response?.data instanceof Blob) {
      const text = await error.response.data.text()
      try {
        detail = JSON.parse(text).detail || text
      } catch {
        detail = text
      }
    }
    ElMessage.error(detail || '导出失败')
  } finally {
    exporting.value = false
  }
}

const onDelete = (row) => {
  ElMessageBox.confirm(`确认删除材料 ${row.name} 吗？`, '提示', { type: 'warning' })
    .then(async () => {
      await deleteMaterial(row.id)
      ElMessage.success('删除成功')
      loadMaterials()
    })
    .catch(() => {})
}

const onSubmitAudit = async (row) => {
  await submitMaterial(row.id)
  ElMessage.success('已提交审核')
  loadMaterials()
}

const onApprove = async (row) => {
  await approveMaterial(row.id)
  ElMessage.success('审核通过')
  loadMaterials()
}

const onReject = async (row) => {
  await rejectMaterial(row.id)
  ElMessage.success('审核拒绝')
  loadMaterials()
}

const canEdit = (row) => isAdmin.value || row.status === 'draft'
const canDelete = (row) => isAdmin.value || row.status === 'draft'
const canSubmit = (row) => !isAdmin.value && row.status === 'draft'
const canApprove = (row) => isAdmin.value && row.status === 'pending'

const goDetail = (row) => {
  router.push(`/materials/${row.id}`)
}

const onPageChange = (page) => {
  pagination.page = page
  loadMaterials()
}

const onPageSizeChange = (size) => {
  pagination.pageSize = size
  pagination.page = 1
  loadMaterials()
}

onMounted(() => {
  loadChoices()
  loadFilterSubcategories()
  loadBrandFilterOptions()
  loadFactoryFilterOptions()
  loadMaterials()
})
</script>

<style scoped>
.toolbar {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.toolbar-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.toolbar-row--advanced {
  padding: 8px 10px;
  background: #f5f7fa;
  border-radius: 4px;
}

.toolbar-spacer {
  flex: 1 1 auto;
}

.advanced-badge :deep(.el-badge__content.is-dot) {
  top: 6px;
  right: 6px;
}

.column-setting__group {
  margin-bottom: 12px;
}

.column-setting__header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.column-setting__title {
  font-weight: 600;
}

.column-setting__cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px 12px;
}

.column-setting__footer {
  display: flex;
  justify-content: flex-end;
  border-top: 1px solid #ebeef5;
  padding-top: 8px;
}

.stars {
  color: #f7ba2a;
  letter-spacing: 1px;
}

.import-dialog__text {
  color: #606266;
  line-height: 1.6;
}

.import-dialog__actions {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

.material-drawer :deep(.el-drawer__body) {
  padding: 20px 24px;
  overflow-y: auto;
}

.material-drawer :deep(.el-drawer__footer) {
  padding: 12px 24px;
}
</style>
