<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="90px">
      <el-form-item label="素材名称" prop="assetName">
        <el-input v-model="queryParams.assetName" placeholder="请输入素材名称" clearable @keyup.enter="handleQuery" />
      </el-form-item>
      <el-form-item label="素材类型" prop="assetType">
        <el-select v-model="queryParams.assetType" placeholder="请选择素材类型" clearable>
          <el-option v-for="dict in media_asset_type" :key="dict.value" :label="dict.label"
            :value="String(dict.value)" />
        </el-select>
      </el-form-item>
      <el-form-item label="引用状态" prop="quotedFlag">
        <el-select v-model="queryParams.quotedFlag" placeholder="请选择引用状态" clearable style="width: 160px">
          <el-option label="未引用" value="0" />
          <el-option label="已引用" value="1" />
        </el-select>
      </el-form-item>
      <el-form-item label="启用状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="请选择启用状态" clearable style="width: 160px">
          <el-option label="启用" value="1" />
          <el-option label="停用" value="0" />
        </el-select>
      </el-form-item>
      <el-form-item label="上传时间">
        <el-date-picker v-model="dateRange" type="daterange" range-separator="-" start-placeholder="开始日期"
          end-placeholder="结束日期" value-format="YYYY-MM-DD" style="width: 240px" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="Upload" @click="handleAdd"
          v-hasPermi="['base:mediAasset:add']">上传素材</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
          v-hasPermi="['base:mediAasset:remove']">删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning" plain icon="Download" @click="handleExport"
          v-hasPermi="['base:mediAasset:export']">导出</el-button>
      </el-col>
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="mediAassetList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="缩略图" align="center" width="100">
        <template #default="scope">
          <div class="asset-thumb">
            <image-preview v-if="getPreviewImage(scope.row)" :src="getPreviewImage(scope.row)" :width="54"
              :height="54" />
            <div v-else class="video-thumb">
              <el-icon>
                <VideoPlay />
              </el-icon>
            </div>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="素材名称" align="left" prop="assetName" min-width="180" show-overflow-tooltip />
      <el-table-column label="素材类型" align="center" prop="assetType" width="100">
        <template #default="scope">
          <dict-tag :options="media_asset_type"
            :value="scope.row.assetType != null ? String(scope.row.assetType) : ''" />
        </template>
      </el-table-column>
      <el-table-column label="文件格式" align="center" prop="fileFormat" width="90">
        <template #default="scope">
          <el-tag v-if="scope.row.fileFormat" type="info">{{ scope.row.fileFormat }}</el-tag>
          <span v-else>-</span>
        </template>
      </el-table-column>
      <el-table-column label="文件大小" align="center" prop="fileSize" width="110">
        <template #default="scope">
          <span>{{ formatFileSize(scope.row.fileSize) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="视频时长" align="center" prop="durationSeconds" width="100">
        <template #default="scope">
          <span>{{ formatDuration(scope.row.durationSeconds) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="分辨率" align="center" prop="resolution" width="120">
        <template #default="scope">
          <span>{{ scope.row.resolution || '-' }}</span>
        </template>
      </el-table-column>
      <el-table-column label="引用状态" align="center" prop="quotedFlag" width="100">
        <template #default="scope">
          <el-tag v-if="String(scope.row.quotedFlag) === '1'" type="warning">已引用</el-tag>
          <el-tag v-else-if="String(scope.row.quotedFlag) === '0'" type="info">未引用</el-tag>
          <el-tag v-else type="info">-</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="启用状态" align="center" prop="status" width="100">
        <template #default="scope">
          <el-tag v-if="String(scope.row.status) === '1'" type="success">启用</el-tag>
          <el-tag v-else-if="String(scope.row.status) === '0'" type="info">停用</el-tag>
          <el-tag v-else type="info">-</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="上传时间" align="center" prop="createTime" width="170">
        <template #default="scope">
          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') || '-' }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="240" fixed="right" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="View" @click="handlePreview(scope.row)">预览</el-button>
          <el-button v-if="String(scope.row.status) !== '1'" link type="primary" icon="CircleCheck"
            @click="handleStatusChange(scope.row, '1')" v-hasPermi="['base:mediAasset:edit']">启用</el-button>
          <el-button v-if="String(scope.row.status) === '1'" link type="warning" icon="CircleClose"
            @click="handleStatusChange(scope.row, '0')" v-hasPermi="['base:mediAasset:edit']">停用</el-button>
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
            v-hasPermi="['base:mediAasset:edit']">编辑</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
            v-hasPermi="['base:mediAasset:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
      @pagination="getList" />

    <!-- 添加或修改素材资源对话框 -->
    <el-dialog :title="title" v-model="open" width="760px" append-to-body>
      <el-form ref="mediAassetRef" :model="form" :rules="rules" label-width="110px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="素材名称" prop="assetName">
              <el-input v-model="form.assetName" maxlength="100" show-word-limit placeholder="请输入素材名称" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="素材文件" prop="fileUrl">
              <el-alert v-if="form.id" title="当前为编辑已有素材，可只修改素材名称、启用状态和备注；如需替换文件，再重新上传素材文件。" type="info" show-icon
                :closable="false" class="upload-edit-tip" />
              <el-upload class="asset-uploader" drag :action="uploadUrl" :headers="uploadHeaders"
                :show-file-list="false" :before-upload="beforeUpload" :on-success="handleUploadSuccess"
                :on-error="handleUploadError">
                <el-icon class="el-icon--upload">
                  <UploadFilled />
                </el-icon>
                <div class="el-upload__text">拖拽文件到此处，或 <em>点击上传</em></div>
                <template #tip>
                  <div class="el-upload__tip">
                    {{ form.id ? '如需替换素材文件，请重新上传；不上传则保留原文件。' : '支持 jpg/png/webp 图片和 mp4 视频，文件信息由系统自动解析。' }}
                  </div>
                </template>
              </el-upload>
            </el-form-item>
          </el-col>
          <el-col :span="24" v-if="form.fileUrl">
            <el-descriptions title="文件信息" :column="2" border class="file-info">
              <el-descriptions-item label="素材类型">
                <dict-tag :options="media_asset_type" :value="form.assetType != null ? String(form.assetType) : ''" />
              </el-descriptions-item>
              <el-descriptions-item label="文件格式">{{ form.fileFormat || '-' }}</el-descriptions-item>
              <el-descriptions-item label="文件大小">{{ formatFileSize(form.fileSize) }}</el-descriptions-item>
              <el-descriptions-item label="MIME 类型">{{ form.mimeType || '-' }}</el-descriptions-item>
              <el-descriptions-item label="视频时长">{{ formatDuration(form.durationSeconds) }}</el-descriptions-item>
              <el-descriptions-item label="分辨率">{{ form.resolution || '-' }}</el-descriptions-item>
              <el-descriptions-item label="文件地址" :span="2">
                <el-link v-if="form.fileUrl" type="primary" :href="form.fileUrl" target="_blank" class="file-url-link">
                  {{ form.fileUrl }}
                </el-link>
                <span v-else>-</span>
              </el-descriptions-item>
            </el-descriptions>
          </el-col>
          <el-col :span="24">
            <el-form-item label="启用状态" prop="status">
              <el-radio-group v-model="form.status">
                <el-radio label="1">启用</el-radio>
                <el-radio label="0">停用</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="备注" prop="remark">
              <el-input v-model="form.remark" type="textarea" :rows="3" maxlength="500" show-word-limit
                placeholder="请输入备注" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 素材预览 -->
    <el-dialog title="素材预览" v-model="previewOpen" width="820px" append-to-body @closed="previewAsset = {}">
      <div class="preview-box">
        <img
          v-if="previewAsset.assetType === 'image'"
          :src="previewAsset.fileUrl"
          class="preview-image"
          @error="handlePreviewError"
        />
        <video
          v-else-if="previewAsset.assetType === 'video'"
          :src="previewAsset.fileUrl"
          class="preview-video"
          controls
          @error="handlePreviewError"
        />
        <el-empty v-else description="暂无可预览内容" />
      </div>
    </el-dialog>
  </div>
</template>

<script setup name="MediAasset">
import { listMediAasset, getMediAasset, delMediAasset, addMediAasset, updateMediAasset } from "@/api/base/mediAasset"
import useUserStore from '@/store/modules/user'

const { proxy } = getCurrentInstance()
const { media_asset_type } = useDict('media_asset_type')

const mediAassetList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const selectedRows = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")

const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + '/common/uploadMediaFile')
const uploadHeaders = ref({
  Authorization: 'Bearer ' + useUserStore()?.token
})

const previewOpen = ref(false)
const previewAsset = ref({})
const dateRange = ref([])

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    assetName: undefined,
    assetType: undefined,
    quotedFlag: undefined,
    status: undefined,
    params: {}
  },
  rules: {
    assetName: [
      { required: true, message: "素材名称不能为空", trigger: "blur" },
      { max: 100, message: "素材名称不能超过 100 字", trigger: "blur" }
    ],
    fileUrl: [
      { required: true, message: "请先上传素材文件", trigger: "change" }
    ],
    status: [
      { required: true, message: "请选择启用状态", trigger: "change" }
    ],
    remark: [
      { max: 500, message: "备注不能超过 500 字", trigger: "blur" }
    ]
  }
})

const { queryParams, form, rules } = toRefs(data)

function getList() {
  loading.value = true
  const params = {
    ...queryParams.value,
    params: {
      ...(queryParams.value.params || {})
    }
  }
  if (dateRange.value && dateRange.value.length === 2) {
    params.params.beginCreateTime = dateRange.value[0]
    params.params.endCreateTime = dateRange.value[1]
  }
  listMediAasset(params).then(response => {
    mediAassetList.value = response.rows || []
    total.value = response.total || 0
  }).catch(() => {
    mediAassetList.value = []
    total.value = 0
  }).finally(() => {
    loading.value = false
  })
}

function cancel() {
  open.value = false
  reset()
}

function reset() {
  form.value = {
    id: null,
    assetName: null,
    assetType: null,
    fileUrl: null,
    thumbnailUrl: null,
    fileSize: null,
    fileFormat: null,
    mimeType: null,
    durationSeconds: null,
    resolution: null,
    status: '1',
    quotedFlag: '0',
    remark: null,
    createBy: null,
    createTime: null,
    updateBy: null,
    updateTime: null
  }
  proxy.resetForm("mediAassetRef")
}

function handleQuery() {
  queryParams.value.pageNum = 1
  getList()
}

function resetQuery() {
  dateRange.value = []
  proxy.resetForm("queryRef")
  handleQuery()
}

function handleSelectionChange(selection) {
  selectedRows.value = selection
  ids.value = selection.map(item => item.id)
  single.value = selection.length != 1
  multiple.value = !selection.length
}

function handleAdd() {
  reset()
  open.value = true
  title.value = "上传素材"
}

function handleUpdate(row) {
  reset()
  const _id = row.id || ids.value
  getMediAasset(_id).then(response => {
    const data = response.data || {}
    form.value = {
      ...data,
      assetType: data.assetType != null ? String(data.assetType) : null,
      status: data.status != null ? String(data.status) : '1',
      quotedFlag: data.quotedFlag != null ? String(data.quotedFlag) : '0'
    }
    open.value = true
    title.value = "编辑素材"
  })
}

function submitForm() {
  proxy.$refs["mediAassetRef"].validate(valid => {
    if (valid) {
      const payload = {
        id: form.value.id,
        assetName: form.value.assetName,
        assetType: form.value.assetType,
        fileUrl: form.value.fileUrl,
        thumbnailUrl: form.value.thumbnailUrl,
        fileSize: form.value.fileSize,
        fileFormat: form.value.fileFormat,
        mimeType: form.value.mimeType,
        durationSeconds: form.value.durationSeconds,
        resolution: form.value.resolution,
        status: String(form.value.status),
        quotedFlag: form.value.quotedFlag || '0',
        remark: form.value.remark
      }
      if (form.value.id != null) {
        updateMediAasset(payload).then(() => {
          proxy.$modal.msgSuccess("修改成功")
          open.value = false
          getList()
        })
      } else {
        addMediAasset(payload).then(() => {
          proxy.$modal.msgSuccess("上传成功")
          open.value = false
          getList()
        })
      }
    }
  })
}

function handleDelete(row) {
  const _ids = row.id || ids.value
  let confirmMsg = '确认删除选中的素材吗？如素材已被播放方案引用，将无法删除。'
  if (row && String(row.quotedFlag) === '1') {
    confirmMsg = '该素材已被播放方案引用，删除可能会失败。确认继续删除吗？'
  } else if (!row && selectedRows.value.some(item => String(item.quotedFlag) === '1')) {
    confirmMsg = '选中的素材中包含已被播放方案引用的素材，删除可能会失败。确认继续删除吗？'
  }
  proxy.$modal.confirm(confirmMsg).then(function () {
    return delMediAasset(_ids)
  }).then(() => {
    getList()
    proxy.$modal.msgSuccess("删除成功")
  }).catch(() => { })
}

function handleExport() {
  const params = {
    ...queryParams.value,
    params: {
      ...(queryParams.value.params || {})
    }
  }
  if (dateRange.value && dateRange.value.length === 2) {
    params.params.beginCreateTime = dateRange.value[0]
    params.params.endCreateTime = dateRange.value[1]
  }
  proxy.download('base/mediAasset/export', params, `素材管理_${new Date().getTime()}.xlsx`)
}

function getPreviewImage(row) {
  if (row.thumbnailUrl) return row.thumbnailUrl
  if (String(row.assetType) === 'image' && row.fileUrl) return row.fileUrl
  return ''
}

function formatFileSize(size) {
  const value = Number(size)
  if (!value) return '-'
  if (value < 1024) return value + ' B'
  if (value < 1024 * 1024) return (value / 1024).toFixed(1) + ' KB'
  if (value < 1024 * 1024 * 1024) return (value / 1024 / 1024).toFixed(1) + ' MB'
  return (value / 1024 / 1024 / 1024).toFixed(1) + ' GB'
}

function formatDuration(seconds) {
  const value = Number(seconds)
  if (!value) return '-'
  const m = Math.floor(value / 60)
  const s = value % 60
  return m > 0 ? `${m}分${s}秒` : `${s}秒`
}

function beforeUpload(file) {
  const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'video/mp4']
  const isAllowed = allowedTypes.includes(file.type)
  const isLt500M = file.size / 1024 / 1024 <= 500
  if (!isAllowed) {
    proxy.$modal.msgError('仅支持 jpg、png、webp 图片和 mp4 视频')
    return false
  }
  if (!isLt500M) {
    proxy.$modal.msgError('素材文件大小不能超过 500MB')
    return false
  }
  return true
}


function handleUploadSuccess(response) {
  const data = response.data || response || {}
  const isSuccess = response.code === 200 || response.code === undefined

  if (!isSuccess) {
    proxy.$modal.msgError(response.msg || '上传失败')
    return
  }

  form.value.assetType = null
  form.value.fileFormat = null
  form.value.mimeType = null
  form.value.durationSeconds = null
  form.value.resolution = null
  form.value.fileSize = null

  const rawName = data.assetName || data.originalFilename || data.fileName || data.newFileName || ''
  if (rawName) {
    const nameWithoutExt = rawName.replace(/\.[^/.]+$/, "")
    if (!form.value.assetName) {
      form.value.assetName = nameWithoutExt
    }
  }

  form.value.fileUrl = data.fileUrl || data.url || form.value.fileUrl

  if (data.assetType) {
    form.value.assetType = String(data.assetType)
  } else {
    const mimeType = (data.mimeType || '').toLowerCase()
    const fileFormat = (data.fileFormat || '').toLowerCase()
    const fileName = (data.originalFilename || data.fileName || data.newFileName || '').toLowerCase()
    if (mimeType.startsWith('video/') || fileFormat === 'mp4' || fileName.endsWith('.mp4')) {
      form.value.assetType = 'video'
    } else if (mimeType.startsWith('image/') || ['jpg', 'jpeg', 'png', 'webp'].includes(fileFormat) || /\.(jpg|jpeg|png|webp)$/.test(fileName)) {
      form.value.assetType = 'image'
    } else {
      form.value.assetType = null
    }
  }

  const nextAssetType = data.assetType ? String(data.assetType) : form.value.assetType
  if (data.thumbnailUrl) {
    form.value.thumbnailUrl = data.thumbnailUrl
  } else if (nextAssetType === 'image') {
    form.value.thumbnailUrl = data.fileUrl || data.url || form.value.fileUrl
  } else {
    form.value.thumbnailUrl = null
  }

  form.value.id = data.id || form.value.id
  form.value.fileSize = data.fileSize
  form.value.fileFormat = data.fileFormat
  form.value.mimeType = data.mimeType
  form.value.durationSeconds = data.durationSeconds
  form.value.resolution = data.resolution
  form.value.status = data.status != null ? String(data.status) : (form.value.status || '1')
  form.value.quotedFlag = data.quotedFlag != null ? String(data.quotedFlag) : (form.value.quotedFlag || '0')

  proxy.$modal.msgSuccess('上传成功')
  proxy.$refs["mediAassetRef"]?.validateField?.("fileUrl")
}

function handleUploadError(error) {
  console.error('素材上传失败：', error)
  proxy.$modal.msgError('素材上传失败，请检查文件格式、文件大小或稍后重试')
}

function handlePreview(row) {
  if (!row.fileUrl) {
    proxy.$modal.msgWarning('暂无可预览文件')
    return
  }
  if (!['image', 'video'].includes(String(row.assetType))) {
    proxy.$modal.msgWarning('暂不支持该素材类型预览')
    return
  }
  previewAsset.value = {
    ...row,
    assetType: String(row.assetType || '')
  }
  previewOpen.value = true
}

function handlePreviewError() {
  proxy.$modal.msgWarning('素材文件暂无法预览，请检查文件地址是否有效。')
}

function handleStatusChange(row, status) {
  const actionText = status === '1' ? '启用' : '停用'
  proxy.$modal.confirm('确认' + actionText + '素材“' + row.assetName + '”吗？').then(() => {
    return updateMediAasset({
      id: row.id,
      assetName: row.assetName,
      assetType: row.assetType,
      fileUrl: row.fileUrl,
      thumbnailUrl: row.thumbnailUrl,
      fileSize: row.fileSize,
      fileFormat: row.fileFormat,
      mimeType: row.mimeType,
      durationSeconds: row.durationSeconds,
      resolution: row.resolution,
      quotedFlag: row.quotedFlag || '0',
      remark: row.remark,
      status
    })
  }).then(() => {
    proxy.$modal.msgSuccess(actionText + '成功')
    getList()
  }).catch(() => { })
}

getList()
</script>

<style scoped>
.asset-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.video-thumb {
  width: 54px;
  height: 54px;
  border-radius: 6px;
  background: #f5f7fa;
  border: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #909399;
  font-size: 24px;
}

.file-info {
  margin: 10px 0 18px;
}

.preview-box {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 360px;
}

.preview-image {
  max-width: 100%;
  max-height: 70vh;
  border-radius: 6px;
}

.preview-video {
  width: 100%;
  max-height: 70vh;
  border-radius: 6px;
  background: #000;
}

.upload-edit-tip {
  margin-bottom: 12px;
}

.file-url-link {
  max-width: 100%;
  word-break: break-all;
}
</style>
