<template>
  <div class="video-post-container">
    <el-row :gutter="20">
      <el-col :md="14" :sm="24">
        <uploader-card
          v-if="uploadConfig"
          ref="videoUploader"
          :upload-config="uploadConfig"
          @before-upload="handleVideoAdded"
          @success="handleVideoSuccess"
        />

        <el-card class="box-card shadow-box" style="margin-top: 20px;">
          <div slot="header" class="clearfix">
            <span>视频封面</span>
            <span class="header-tip">（支持 JPG/PNG，小于 10MB）</span>
          </div>
          <div class="cover-upload-wrapper">
            <el-upload
              v-if="imgOssUrl !== ''"
              class="avatar-uploader"
              :action="imgOssUrl"
              :headers="imgHeaders"
              :data="imgData"
              :show-file-list="false"
              :before-upload="beforeCoverUpload"
              :on-success="handleManualCoverSuccess"
            >
              <div v-if="coverUrl" class="cover-preview">
                <img :src="coverUrl" class="avatar">
                <div class="cover-mask">
                  <i class="el-icon-edit" />
                  <span>更换封面</span>
                </div>
              </div>
              <i v-else class="el-icon-plus avatar-uploader-icon" />
            </el-upload>
            <div class="cover-info-text">
              <p>温馨提示：</p>
              <ul>
                <li>好的封面能大幅提升点击率</li>
                <li>系统已尝试为您自动截取视频首帧</li>
              </ul>
            </div>
          </div>
        </el-card>
      </el-col>

      <el-col :md="10" :sm="24">
        <el-card class="box-card shadow-box">
          <div slot="header" class="clearfix">
            <span>稿件信息</span>
            <el-button
              type="primary"
              size="small"
              style="float: right;"
              :loading="submitting"
              @click="submitForm"
            >立即发布</el-button>
          </div>

          <el-form ref="postForm" :model="form" :rules="rules" label-position="top">
            <el-form-item label="视频标题" prop="title">
              <el-input
                v-model="form.title"
                placeholder="给视频起个好名字吧"
                maxlength="50"
                show-word-limit
              />
            </el-form-item>

            <el-form-item label="视频简介" prop="description">
              <el-input
                v-model="form.description"
                type="textarea"
                :rows="4"
                placeholder="介绍一下你的视频吧..."
              />
            </el-form-item>

            <el-form-item v-if="!isEdit" label="选择分区" prop="categoryId">
              <el-row :gutter="10">
                <el-col :span="12">
                  <el-select v-model="form.categoryPid" placeholder="一级分区" @change="handlePCategoryChange">
                    <el-option
                      v-for="item in pCategoryList"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-col>
                <el-col :span="12">
                  <el-select v-model="form.categoryId" placeholder="二级分区">
                    <el-option
                      v-for="item in subCategoryList"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-col>
              </el-row>
            </el-form-item>

            <el-form-item v-if="!isEdit" label="标签" prop="tags">
              <el-select
                v-model="form.tags"
                multiple
                filterable
                allow-create
                default-first-option
                placeholder="按回车添加标签"
                style="width: 100%;"
              >
                <el-option
                  v-for="tag in recommendTags"
                  :key="tag"
                  :label="tag"
                  :value="tag"
                />
              </el-select>
            </el-form-item>

            <el-form-item v-if="!isEdit" label="权限设置">
              <el-radio-group v-model="form.scope">
                <el-radio label="1">私有</el-radio>
                <el-radio label="2">公开</el-radio>
                <el-radio label="3">VIP可见</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-form>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import UploaderCard from 'components/card/UploaderCard.vue'
import { addVideoFile, updateVideoCover, updateVideoFile, videoRegion } from '@/api/vod'
import { getVideoChannelInfo, getVideoCoverChannelInfo } from '@/api/file'

export default {
  name: 'VideoPostPublish',
  components: { UploaderCard },
  props: {
    // 接收视频信息，null 为发布，非 null 为编辑
    videoInfo: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      uploadConfig: null,
      // 封面上传相关
      imgOssUrl: '',
      imgHeaders: { Authorization: '' },
      imgData: { clientSha256sum: null },
      coverUrl: null,

      // 分区数据
      pCategoryList: [],
      subCategoryList: [],
      categoryRawData: [],
      recommendTags: ['动画', '生活', '科技', '美食', '游戏'],

      // 表单数据
      submitting: false,
      form: {
        videoId: null,
        coverFileId: null,
        title: '',
        description: '',
        categoryPid: null,
        categoryId: null,
        tags: [],
        scope: '2'
      },

      // 校验规则
      rules: {
        title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
        categoryId: [{ required: true, message: '请选择完整的分区', trigger: 'change' }],
        tags: [{ type: 'array', required: true, message: '请至少添加一个标签', trigger: 'change' }]
      }
    }
  },
  computed: {
    isEdit() {
      return this.videoInfo !== null
    }
  },
  watch: {
    // 监听 props 变化，防止父组件异步获取数据后子组件不更新
    videoInfo: {
      handler(val) {
        if (val) {
          this.initEditData(val)
        }
      },
      immediate: true
    },
    // 监听原始分区数据加载完毕后，如果处于编辑模式，初始化二级分区列表
    categoryRawData(val) {
      if (val && val.length > 0 && this.form.categoryPid) {
        this.handlePCategoryChange(this.form.categoryPid, true)
      }
    }
  },
  created() {
    this.initCategoryData()
    this.initUploadConfig()
  },
  methods: {
    // 初始化编辑数据
    initEditData(info) {
      this.form = {
        videoId: info.videoId,
        coverFileId: info.coverFileId || null,
        title: info.title || '',
        description: info.description || '',
        categoryPid: info.categoryPid || null,
        categoryId: info.categoryId || null,
        tags: Array.isArray(info.tags) ? info.tags : (info.tags ? info.tags.split(',') : []),
        scope: String(info.scope || '2')
      }
      this.coverUrl = info.coverUrl || null

      // 如果数据已准备好，立即触发二级分区列表
      if (this.categoryRawData.length > 0) {
        this.handlePCategoryChange(this.form.categoryPid, true)
      }
    },
    // 1. 初始化数据
    async initCategoryData() {
      const res = await videoRegion()
      if (res.code === 0) {
        this.categoryRawData = res.data
        this.pCategoryList = res.data.map(item => ({ label: item.label, value: item.value }))
      }
    },

    initUploadConfig() {
      getVideoChannelInfo().then(resp => {
        if (resp.code === 0) {
          this.uploadConfig = resp.data
          this.uploadConfig.title = this.isEdit ? '重新上传视频文件' : '上传视频文件'
          this.uploadConfig.fileAttrs = { accept: 'video/*' }
        } else {
          this.$message.warning(resp.msg)
        }
      })

      getVideoCoverChannelInfo().then(res => {
        if (res.code === 0) {
          this.imgOssUrl = res.data.ossUrl
          this.imgHeaders.Authorization = 'Bearer ' + res.data.token
        } else {
          this.$message.warning(res.msg)
        }
      })
    },

    // 2. 视频上传组件回调
    handleVideoAdded(filename) {
      // 仅在发布模式下，上传视频后自动填充标题
      if (!this.isEdit && !this.form.title) {
        this.form.title = filename.replace(/\.[^/.]+$/, '').substring(0, 50)
      }
    },

    handleVideoSuccess(uploadResult) {
      if (this.isEdit) {
        const videoFile = {
          videoId: this.videoInfo.videoId,
          videoFileId: uploadResult.uploadId
        }
        updateVideoFile(videoFile).then(res => {
          this.$message.info(res.msg)
        }).catch(error => {
          this.$message.error(error.message)
        })
      } else {
        const { uploadId, file } = uploadResult
        // 自动截取视频封面
        this.generateLocalCover(file.file)

        addVideoFile({
          videoFileId: uploadId,
          filename: file.name
        }).then(resp => {
          if (resp.code === 0) {
            this.form.videoId = resp.data
            this.$message.info('视频处理完成')
          } else {
            this.$message.warning(resp.msg)
          }
        })
      }
    },
    generateLocalCover(rawFile) {
      const video = document.createElement('video')
      video.src = URL.createObjectURL(rawFile)
      video.muted = true
      video.play() // 必须播放或设置 currentTime 才能截取

      video.onloadeddata = () => {
        video.currentTime = 1 // 截取第 1 秒的画面
      }

      video.onseeked = () => {
        const canvas = document.createElement('canvas')
        canvas.width = video.videoWidth
        canvas.height = video.videoHeight
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)

        canvas.toBlob((blob) => {
          // 这里的 blob 才是 handleAutoFrame 真正需要的参数
          this.handleAutoFrame(blob)
          URL.revokeObjectURL(video.src)
        }, 'image/jpeg', 0.9)
      }
    },
    // 处理自动截取的封面
    async handleAutoFrame(blobFile) {
      // 封装 FormData 手动上传截取的封面
      const formData = new FormData()
      formData.append('file', blobFile)
      formData.append('clientSha256sum', '')

      fetch(this.imgOssUrl, {
        method: 'POST',
        headers: this.imgHeaders,
        body: formData
      })
        .then(res => res.json())
        .then(json => {
          if (json.code === 0) {
            this.form.coverFileId = json.data.uploadId
            this.coverUrl = URL.createObjectURL(blobFile)
          }
        })
    },

    // 3. 封面手动上传逻辑
    beforeCoverUpload(file) {
      const isType = ['image/jpeg', 'image/png'].includes(file.type)
      const isLt10M = file.size / 1024 / 1024 < 10
      if (!isType) this.$message.error('封面只能是 JPG 或 PNG 格式!')
      if (!isLt10M) this.$message.error('封面大小不能超过 10MB!')

      if (isType && isLt10M) {
        this.imgData.clientSha256sum = ''
      }

      return isType && isLt10M
    },

    handleManualCoverSuccess(res, file) {
      if (res.code === 0) {
        if (this.isEdit) {
          const videoCover = {
            videoId: this.videoInfo.videoId,
            coverUrl: res.data.url,
            coverFileId: res.data.uploadId
          }
          updateVideoCover(videoCover).then(res => {
            this.$message.info(res.msg)
          }).catch(error => {
            this.$message.error(error.message)
          })
        } else {
          this.form.coverFileId = res.data.uploadId
          this.coverUrl = URL.createObjectURL(file.raw)
          this.$message.success('封面上传成功')
        }
      }
    },

    // 4. 分区联动
    handlePCategoryChange(pid, isInit = false) {
      if (!isInit) {
        this.form.categoryId = null
      }
      const parent = this.categoryRawData.find(i => i.value === pid)
      this.subCategoryList = parent ? parent.children : []
    },

    // 5. 最终提交
    submitForm() {
      this.$refs.postForm.validate((valid) => {
        if (!valid) return
        if (!this.form.videoId) {
          return this.$message.warning('请等待视频上传完成')
        }

        this.submitting = true
        // 向上抛出事件，带上模式标识
        this.$emit('video-publish', {
          data: this.form,
          mode: this.isEdit ? 'edit' : 'publish'
        })

        setTimeout(() => { this.submitting = false }, 1000)
      })
    }
  }
}
</script>

<style scoped lang="scss">
.video-post-container {
  padding: 20px;
  background-color: #f4f5f7;
  min-height: 100vh;

  .shadow-box {
    border: none;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
  }

  .header-tip {
    font-size: 12px;
    color: #9499a0;
    margin-left: 10px;
  }
}

/* 封面上传样式 */
.cover-upload-wrapper {
  display: flex;
  gap: 20px;
  align-items: center;

  .avatar-uploader {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    overflow: hidden;
    width: 240px;
    height: 150px;
    &:hover { border-color: #409EFF; }
  }

  .cover-preview {
    position: relative;
    width: 100%;
    height: 100%;
    .avatar { width: 100%; height: 100%; object-fit: cover; }
    .cover-mask {
      position: absolute; top: 0; left: 0; width: 100%; height: 100%;
      background: rgba(0,0,0,0.5); color: #fff;
      display: flex; flex-direction: column; justify-content: center; align-items: center;
      opacity: 0; transition: opacity 0.3s;
    }
    &:hover .cover-mask { opacity: 1; }
  }

  .avatar-uploader-icon {
    font-size: 28px; color: #8c939d;
    width: 240px; height: 150px; line-height: 150px; text-align: center;
  }

  .cover-info-text {
    flex: 1;
    font-size: 13px; color: #61666d;
    ul { padding-left: 18px; margin-top: 8px; color: #9499a0; }
  }
}
</style>
