<template>
  <div class="app-container">
    <div class="filter-container">
      <div class="filter-container-lt">
        <el-form :inline="true" label-position="left" :model="listQuery">
          <el-form-item>
            <el-input clearable v-model="listQuery.sku" placeholder="搜索SKU"
            ></el-input>
          </el-form-item>
          <el-form-item>
            <el-select clearable v-model="listQuery.status" placeholder="请选择状态">
              <el-option
                v-for="item in statusSets"
                :key="item.value"
                :label="item.label"
                :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
          <el-button type="primary" @click="getList()">搜索</el-button >
          <el-button type="primary" @click="showCropSizeModal()">裁图尺寸</el-button >
          <el-button type="primary" @click="aiCropPreview()" :loading="uploadLoading">AI裁图</el-button>
        </el-form>
      </div>
    </div>
    <div class="table-container">
      <el-table  style="width: 100%" v-loading="listLoading" :key="tableKey" :data="list" row-key="id"
        stripe border fit highlight-current-row @selection-change="handleSelectionChange">
        <!-- <el-table-column type="selection" width="55" :selectable="selectable"></el-table-column> -->
        <el-table-column label="SKU名称" align="center">
          <template slot-scope="scope">
            <el-popover
              placement="bottom"
              width="260"
              trigger="manual"
              v-model="scope.row._popoverVisible"
            >
              <div class="input-block">
                <span style="display: block;">SKU:</span>
                <el-input
                  v-model="editValue"
                  type="textarea"
                  :rows="2"
                />
              </div>
              <div class="input-block" style="margin-top: 10px;" v-if="scope.row.status >= 5">
                <span style="display: block;">颜色代码:</span>
                <el-input
                  v-model="editValueColor"
                  type="textarea"
                  :rows="2"
                />
              </div>

              <div class="popover-footer">
                <el-button size="mini" @click="cancelEdit(scope.row)">取消</el-button>
                <el-button size="mini" :loading="skuLoading" type="primary" @click="confirmEdit(scope.row)">确认</el-button>
              </div>

              <span slot="reference" class="click-text" @click="openEdit(scope.row)">
                {{ scope.row.sku }} 
                <template v-if="scope.row.colorCode">
                  <br>
                  {{ scope.row.colorCode }}
                </template>
              </span>
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column label="原图" min-width="100" align="center">
          <template slot-scope="scope">
            <p v-if="scope.row.type == 1 && scope.row.referenceImagesList && scope.row.referenceImagesList.length" @click="openGallery(scope.row, 'default')">
              <img style="max-width: 100px;"  :src="scope.row.referenceImagesList[0]"  alt=""></img>
            </p>
            <p style="margin: 0;cursor: pointer;" v-if="scope.row.type == 2 && scope.row.aiGeneratedImageVOList && scope.row.aiGeneratedImageVOList.filter(acc => acc.imageType == 1).length" @click="openGallery(scope.row, 'default')">
              <img style="max-width: 100px;"  :src="scope.row.aiGeneratedImageVOList.filter(acc => acc.imageType == 1)[0].imageUrl"  alt="">
            </p>
          </template>
        </el-table-column>
        <el-table-column label="AI生成图" min-width="100" align="center">
          <template slot-scope="scope">
            <p style="margin: 0;cursor: pointer;" v-if="scope.row.aiGeneratedImageVOList && scope.row.aiGeneratedImageVOList.length" @click="openGallery(scope.row)">
              <img style="max-width: 100px;"  :src="scope.row.aiGeneratedImageVOList.filter(acc => acc.imageType == 1)[0].imageUrl"  alt="">
            </p>
          </template>
        </el-table-column>
        <el-table-column label="预计完成时间" min-width="100" align="center" prop="expectedCompletionTime" />
        <el-table-column label="状态" min-width="100" align="center">
          <template slot-scope="scope">
            <el-tag v-if="scope.row.status == 0">提交中</el-tag>
            <el-tag v-if="scope.row.status == 1">AI生成中</el-tag>
            <el-tag type="warning" v-if="scope.row.status == 2">待审核</el-tag>
            <el-tag type="warning" v-if="scope.row.status == 3">待复核</el-tag>
            <el-tag type="success" v-if="scope.row.status == 4">待裁图</el-tag>
            <el-tag type="warning" v-if="scope.row.status == 5">裁图待复核</el-tag>
            <el-tag type="success" v-if="scope.row.status == 6">已完成</el-tag>
            <el-tag type="danger" v-if="scope.row.status == 7">生图失败</el-tag>
            <el-tag v-if="scope.row.status == 8">待推送</el-tag>
            <el-tag v-if="scope.row.status == 9">裁图中</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="处理人" min-width="100" align="center" prop="creator" />
        <el-table-column label="处理时间" min-width="100" align="center" prop="updateTime" />
        <el-table-column label="操作" align="center" width="250" fixed="right">
          <template slot-scope="scope">
            <!-- scope.row.status == 2 || scope.row.status == 3 -->
            <el-button size="mini" v-if="scope.row.status == 2 || scope.row.status == 3" @click="showImagesGroupModal(scope.row, 'review')">审核</el-button>
            <el-button type="success" size="mini" v-if="scope.row.status * 1 >= 4 && scope.row.status != 7 && scope.row.status != 9 && scope.row.status != 6" @click="showImagesGroupModal(scope.row, 'crop')">裁图</el-button>
            <el-button type="primary" v-if="scope.row.status * 1 > 1 && scope.row.status != 7" size="mini" @click="handleDownload(scope.row)">下载</el-button>
            <!-- 自动生成 1 手动生成 2 -->
            <el-button type="info" size="mini" v-if="scope.row.type != 2" @click="handleRegenerate(scope.row)">重生成</el-button>

            <el-dropdown v-if="scope.row.status == 8" @command="uploadGalleryList($event, scope.row)">
              <el-button type="warning" size="mini">
                上传图库<i class="el-icon-arrow-down el-icon--right"></i>
              </el-button>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item command="1">覆盖模式</el-dropdown-item>
                <el-dropdown-item command="2">追加模式</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
            <el-popover
              placement="left"
              width="320"
              trigger="click"
            >
              <!-- 日志内容 -->
              <div v-if="scope.row.operationLogs && scope.row.operationLogs.length" style="max-height: 500px;overflow-y: auto;">
                <div
                  v-for="(log, index) in scope.row.operationLogs"
                  :key="index"
                  class="log-item"
                >
                  <div class="log-user">{{ log.userName }}</div>
                  <div class="log-action">{{ log.msg }}</div>
                  <div class="log-time">{{ log.updateTime }}</div>
                </div>
              </div>

              <div v-else class="empty-log">
                暂无操作日志
              </div>

              <!-- 触发按钮 -->
              <el-button
                slot="reference"
                size="mini"
                type="danger"
              >
                操作日志
              </el-button>
            </el-popover>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 分页 -->
    <swPage v-if="total > 0" key="2" :listQuery="listQuery" :total="total" pos="btmRight" @retPage="retPage" />
    <crop-size-modal ref="CropSizeModal" :list="sizeList" @success="getSizeTemplate()"></crop-size-modal>
    <images-group-modal ref="ImagesGroupModal" :sizeList="sizeList" @update-status="updateStatus" @update-images="updateImages" @update-success="handleFilter()"></images-group-modal>
  </div>
</template>

<script>
import waves from "@/directive/waves";
import swPage from "@/views/common/swPage";
import CropSizeModal from "./components/CropSizeModal";
import ImagesGroupModal from "./components/ImagesGroupModal";
import { auditStatus } from "@/constants/index";
import { getValueByKey } from "@/utils/index";
import permission from "@/directive/permission";
import { genCidHex16 } from '@/utils/index'
import { Fancybox } from "@fancyapps/ui";
import request from '@/utils/request'
import "@fancyapps/ui/dist/fancybox.css";
import JSZip from 'jszip'
import { saveAs } from 'file-saver'

export default {
  name: "cropList",
  directives: {
    waves,
    permission
  },
  components: {
    swPage,
    CropSizeModal,
    ImagesGroupModal
  },
  computed: {
  },
  data() {
    return {
      auditStatus,
      tableKey: 0,
      list: [],
      total: 0,
      skuLoading: false,
      editValue: '',
      editValueColor: '',
      listLoading: false,
      uploadLoading: false,
      listQuery: {
        currentPage: 1,
        pageSize: 10,
        sku: null,
        status: ''
      },
      sizeList: [],
      multipleSelection: []
    };
  },
  //页面创建的时候执行
  created() {
    this.getSizeTemplate();
    this.getList();
  },
  computed: {
    statusSets() {
      return [
        {label: '提交中', value: '0'},
        {label: 'AI生成中', value: '1'},
        {label: '待审核', value: '2'},
        {label: '待复核', value: '3'},
        {label: '待裁图', value: '4'},
        {label: '裁图待复核', value: '5'},
        {label: '已完成', value: '6'},
        {label: '生图失败', value: '7'},
        {label: '待推送', value: '8'},
        {label: '裁图中', value: '9'}
      ]
    }
  },
  mounted() {
    document.addEventListener('click', this.handleClickOutside)
  },
  beforeDestroy() {
    document.removeEventListener('click', this.handleClickOutside)
  },
  methods: {
    aiCropPreview() {
      this.$refs.ImagesGroupModal.init();
    },
    selectable(row, index) {
      // 返回 false → 该行不可选
      // 返回 true  → 该行可选
      return row.status == 6 || row.status == 8;
    },
    handleRegenerate(row) {
      this.listLoading = true;
      request({
        url: '/imageTask/regenerate',
        method: 'post',
        data: {
          sessionId: `${Date.now() + 10}_${genCidHex16()}`,
          applicationId: 5,
          id: row.id,
        }
      }).then(res => {
        if (res.code == 200) {
          this.getList();
          this.$message.success("操作成功");
        }
      }).finally(() => {
        this.listLoading = false;
      })
    },
    getSizeTemplate() {
      request({
        url: '/sizeTemplate/list',
        method: 'get'
      }).then(res => {
        if (res.code == 200) {
          this.sizeList = res.data;
        }
      }).finally(() => {
        
      })
    },
    updateImages(id, imageId){
      this.list.forEach(item => {
        if (item.id == id) {
          item.aiGeneratedImageVOList.map((acc, index) => {
            if (acc.id == imageId) {
              item.aiGeneratedImageVOList.splice(index, 1); 
            }
          })
        }
      })
    },
    updateStatus(id, status) {
      this.list.forEach(item => {
        if (item.id == id) {
          item.status = status;
        }
      })
    },
    handleClickOutside(e) {
      // 如果点击发生在 popover 或 reference 内，不处理
      const popovers = document.querySelectorAll('.el-popover')
      const references = document.querySelectorAll('.click-text')

      for (let el of [...popovers, ...references]) {
        if (el.contains(e.target)) return
      }

      // 否则关闭所有 popover
      this.list.forEach(item => {
        item._popoverVisible = false
      })
    },
    openEdit(row) {
      // 先关闭所有 popover
      this.list.forEach(item => {
        item._popoverVisible = false;
      })
      row._popoverVisible = true;
      this.editValue = row.sku;
      this.editValueColor = row.colorCode;
    },
    cancelEdit(row) {
      row._popoverVisible = false
    },
    confirmEdit(row) {
      // 👉 这里可直接调用保存接口
      const params = {
        sessionId: `${Date.now() + 10}_${genCidHex16()}`,
        applicationId: 5,
        id: row.id,
        sku: this.editValue
      }
      if (row.status >= 5) {
        params['colorCode'] = this.editValueColor;
      }
      this.skuLoading = true;
      request({
        url: '/imageTask/update',
        method: 'post',
        data: params
      }).then(res => {
        if (res.code == 200) {
          row._popoverVisible = false;
          row.sku = this.editValue;
          if (row.status >= 5) {
            row.colorCode = this.editValueColor;
          }
          this.$message.success("操作成功");
        }
      }).finally(() => {
        this.skuLoading = false;
      })
    },
    getValueByKey,
    getList() {
      this.listLoading = true;
      const params = {}
      for (const key in this.listQuery) {
        const value = this.listQuery[key]
        if (value !== null && value !== '' && value !== undefined) {
          params[key] = value
        }
      }
      request({
        url: '/imageTask/page',
        method: 'get',
        params: params
      }).then(res => {
        if (res.code == 200) {
          this.total = res.data.total;
          this.list = res.data.rows;
        }
      }).finally(() => {
        this.listLoading = false
      })
    },
    retPage() {
      //分页
      this.getList();
    },
    handleFilter() {
      this.listQuery.page = 1;
      this.getList();
    },
    // 上传图库
    uploadGalleryList(command, row) {
      this.listLoading = true;
      const params = {
        taskId: row.id,
        uploadType: command || '2'
      }
      request({
        url: '/imageTask/uploadGallery',
        method: 'post',
        data: params
      }).then(res => {
        if (res.code == 200) {
          this.$message.success(res.msg || '操作成功!');
        }
      }).finally(() => {
        this.listLoading = false
      })
    },
    openGallery(row, type) {
      let images = [];
      if (type == 'default') {
        if (row.type == 1) {
          images = [...row.referenceImagesList, ...row.originalImagesList].slice(0, 10);
        } else {
          images = row.aiGeneratedImageVOList.filter(acc => acc.imageType == 1).slice(0, 10).map(acc => {
            return acc.imageUrl
          });
        }
      } else {
        if (row.type == 1) {
          row.aiGeneratedImageVOList.filter(acc => acc.imageType == 1).slice(0, 10).forEach(acc => {
            images.push(acc.imageUrl)
          })
        } else {
          row.aiGeneratedImageVOList.filter(acc => acc.imageType == 2).slice(0, 10).forEach(acc => {
            images.push(acc.imageUrl)
          })
        }
      }

      Fancybox.show(
        images.map((src) => ({
          src,
          type: "image",
        })),
        {
          startIndex: 0,
        }
      );
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    async runWithConcurrencyLimit(tasks, limit = 5) {
      const executing = []
      const results = []

      for (const task of tasks) {
        const p = Promise.resolve().then(task)
        results.push(p)
        executing.push(p)

        p.finally(() => {
          const index = executing.indexOf(p)
          if (index > -1) executing.splice(index, 1)
        })

        if (executing.length >= limit) {
          await Promise.race(executing)
        }
      }

      return Promise.allSettled(results)
    },
    async handleDownload(row) {
      const imagesList = row.aiGeneratedImageVOList
      if (!imagesList || !imagesList.length) return

      this.listLoading = true

      const zip = new JSZip()
      const folder = zip.folder('images')

      const tasks = imagesList.map((item, index) => async () => {
        try {
          const res = await fetch(item.imageUrl)
          const blob = await res.blob()

          // 更安全的文件名解析
          const urlObj = new URL(item.imageUrl)
          const fileName = urlObj.pathname.split('/').pop()

          folder.file(fileName || `image_${index + 1}.jpg`, blob)
        } catch (err) {
          console.error('下载失败:', item.imageUrl, err)
        }
      })

      // 并发限制（5 个）
      await this.runWithConcurrencyLimit(tasks, 5)

      const zipBlob = await zip.generateAsync({ type: 'blob' })
      saveAs(zipBlob, `${row.sku || 'images'}.zip`)

      this.listLoading = false
    },
    showCropSizeModal() {
      this.$refs.CropSizeModal.show();
    },
    showImagesGroupModal(row, type) {
      this.$refs.ImagesGroupModal.show(row, type);
    }
  }
};
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
@import "@/styles/layout.scss";

.table-container {
  .el-button+.el-button {
    margin-left: 7px;
    margin-bottom: 10px;
  }
  .el-button+span,
  .el-button+.el-dropdown {
    margin-left: 7px;
  }
}
.button {
  .el-button {
    margin-bottom: 10px;

    &:last-child {
      margin-bottom: 0;
    }
  }
}
.log-item {
  padding: 6px 0;
  border-bottom: 1px dashed #eee;
}

.log-item:last-child {
  border-bottom: none;
}

.log-user {
  font-weight: 500;
  color: #ae8877;
}

.log-action {
  font-size: 13px;
  margin: 2px 0;
}

.log-time {
  font-size: 12px;
  color: #999;
}

.empty-log {
  text-align: center;
  color: #aaa;
  padding: 20px 0;
}
.click-text {
  cursor: pointer;
  color: #409eff;
}

.click-text:hover {
  text-decoration: underline;
}

.popover-footer {
  margin-top: 10px;
  text-align: right;
}


</style>
