<template>
  <div class="photo-album-container">
    <!-- 头部：环境/视频/相册 Tab和新建按钮 -->
    <div class="header-section">
      <el-tabs v-model="activeTab" @tab-click="handleTabClick">
        <!-- <el-tab-pane label="环境" name="environment" />
        <el-tab-pane label="视频" name="video" /> -->
        <el-tab-pane v-for="album in albumList" :key="album.id" :label="album.name" :name="String(album.id)">
          <template #label>
            <span class="album-tab-label">
              {{ album.name }}
              <el-icon class="edit-icon" @click.stop="handleEditAlbum(album)">
                <Edit />
              </el-icon>
            </span>
          </template>
        </el-tab-pane>
      </el-tabs>
      <div class="header-actions">
        <el-button type="primary" @click="openCreateDialog"> 新建相册 </el-button>
      </div>
    </div>

    <!-- 内容区域：isFixed 为「视频」的相册走视频链路，其余相册走原图片链路 -->
    <div class="content-section">
      <div v-if="(isAlbumTab && currentAlbumIsVideo) || activeTab === 'video'" class="upload-tips">
        <span>单个视频上传大小不超过50M，时长建议小于1分钟</span>
      </div>
      <div v-else-if="isAlbumTab && currentAlbumRef && !currentAlbumIsVideo" class="upload-tips">
        <span>照片宽高不小于500像素</span>
        <span>大小不超过10M</span>
        <span>可拖拽排序</span>
        <span>暂不支持上传动图</span>
        <span>不可上传手机截屏、含清晰人脸/电话/二维码/第三方水印/LOGO等图片。</span>
      </div>

      <!-- 相册 Tab：图片（非视频相册） -->
      <div v-if="isAlbumTab && currentAlbumRef && !currentAlbumIsVideo" class="media-grid">
        <div class="upload-item upload-box">
          <UploadImgs
            v-model:file-list="currentAlbumRef.images"
            :limit="50"
            :file-size="10"
            :file-type="['image/jpeg', 'image/png', 'image/gif', 'image/webp']"
            :width="'100%'"
            :height="'200px'"
            :border-radius="'8px'"
            :api="customImageUploadApi"
          >
            <template #tip>
              <div class="upload-tip-text">上传图片 ({{ currentAlbumRef.images?.length || 0 }}/50)</div>
            </template>
          </UploadImgs>
        </div>

        <div v-for="(image, index) in displayImages" :key="image.uid || index" class="media-item">
          <div class="media-wrapper">
            <img :src="image.url || ''" alt="相册图片" />
            <div class="media-overlay">
              <el-button type="primary" link @click="viewImage(image.url || '')"> 查看 </el-button>
              <el-button type="primary" link @click="deleteImage(index)"> 删除 </el-button>
            </div>
            <el-tag v-if="isFirstImage(index)" type="danger" class="cover-tag"> 封面 </el-tag>
          </div>
        </div>
      </div>

      <!-- 相册 Tab：视频（isFixed 为视频） -->
      <div v-else-if="isAlbumTab && currentAlbumRef && currentAlbumIsVideo" class="media-grid">
        <div class="upload-item upload-box">
          <UploadImgs
            v-model:file-list="currentAlbumRef.videos"
            :limit="10"
            :file-size="50"
            :file-type="['video/mp4', 'video/webm', 'video/ogg', 'video/quicktime'] as any"
            :width="'100%'"
            :height="'200px'"
            :border-radius="'8px'"
            :api="customVideoUploadApi"
            :on-success="handleVideoUploadSuccess"
          >
            <template #tip>
              <div class="upload-tip-text">上传视频 ({{ currentAlbumRef.videos?.length || 0 }}/10)</div>
            </template>
          </UploadImgs>
        </div>

        <div v-for="(video, index) in displayVideos" :key="video.uid || index" class="media-item">
          <div class="media-wrapper">
            <video
              v-if="video.url"
              :src="video.url"
              :poster="video.coverUrl || undefined"
              class="media-preview"
              muted
              preload="metadata"
              playsinline
            />
            <!-- imgUrl JSON 内 cover 为封面图，叠在 video 上保证缩略图稳定展示 -->
            <img v-if="video.coverUrl" :src="video.coverUrl" class="media-cover-thumb" alt="视频封面" />
            <div v-else-if="!video.url" class="media-placeholder">
              <el-icon><VideoPlay /></el-icon>
              <span>视频预览</span>
            </div>
            <div class="media-overlay">
              <el-button type="primary" link @click="viewVideo(video.url || '')"> 查看 </el-button>
              <el-button type="primary" link @click="deleteVideo(index)"> 删除 </el-button>
            </div>
          </div>
        </div>
      </div>

      <!-- 独立「视频」Tab（若启用头部 Tab） -->
      <div v-else-if="activeTab === 'video'" class="media-grid">
        <div class="upload-item upload-box">
          <UploadImgs
            v-model:file-list="videoList"
            :limit="10"
            :file-size="50"
            :file-type="['video/mp4', 'video/webm', 'video/ogg', 'video/quicktime'] as any"
            :width="'100%'"
            :height="'200px'"
            :border-radius="'8px'"
            :api="customVideoUploadApi"
            :on-success="handleVideoUploadSuccess"
          >
            <template #tip>
              <div class="upload-tip-text">上传视频 ({{ videoList.length }}/10)</div>
            </template>
          </UploadImgs>
        </div>

        <div v-for="(video, index) in displayVideos" :key="video.uid || index" class="media-item">
          <div class="media-wrapper">
            <video
              v-if="video.url"
              :src="video.url"
              :poster="video.coverUrl || undefined"
              class="media-preview"
              muted
              preload="metadata"
              playsinline
            />
            <img v-if="video.coverUrl" :src="video.coverUrl" class="media-cover-thumb" alt="视频封面" />
            <div v-else-if="!video.url" class="media-placeholder">
              <el-icon><VideoPlay /></el-icon>
              <span>视频预览</span>
            </div>
            <div class="media-overlay">
              <el-button type="primary" link @click="viewVideo(video.url || '')"> 查看 </el-button>
              <el-button type="primary" link @click="deleteVideo(index)"> 删除 </el-button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- 分页 -->
    <div class="pagination-section">
      <el-pagination
        v-model:current-page="pageable.pageNum"
        v-model:page-size="pageable.pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="pageable.total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
    <!-- 新建/编辑相册弹窗 -->
    <el-dialog v-model="createDialogVisible" :title="editId ? '修改相册名称' : '新建相册'" width="500px" @close="resetCreateForm">
      <el-form :model="createForm" :rules="createRules" ref="createFormRef" label-width="0">
        <el-form-item prop="name">
          <el-input v-model="createForm.name" placeholder="请输入相册名称" maxlength="6" clearable show-word-limit />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <div class="footer-left">
            <el-button v-if="editId" type="danger" @click="handleDeleteAlbum"> 删除相册 </el-button>
          </div>
          <div class="footer-right">
            <el-button @click="createDialogVisible = false"> 取消 </el-button>
            <el-button type="primary" @click="handleCreateAlbum"> 确定 </el-button>
          </div>
        </div>
      </template>
    </el-dialog>

    <!-- 视频预览对话框（相册/视频 Tab） -->
    <el-dialog v-model="previewVisible" width="600px" align-center class="preview-dialog">
      <div class="preview-content">
        <video v-if="previewVideoUrl" :src="previewVideoUrl" controls class="preview-video" />
        <img v-else-if="previewImageUrl" :src="previewImageUrl" alt="预览" class="preview-image" />
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch, nextTick } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import type { UploadUserFile } from "element-plus";
import { VideoPlay, Edit } from "@element-plus/icons-vue";
import UploadImgs from "@/components/Upload/Imgs.vue";
import { localGet } from "@/utils";
import {
  getOfficialAlbumList,
  createOrUpdateOfficialAlbum,
  deleteOfficialAlbum,
  saveOfficialImg,
  getOfficialImgList,
  getOfficialVideoByStoreId,
  saveOfficialVideoSaveOrSaveBatch,
  deleteOfficialImg
} from "@/api/modules/storeDecoration";
import { uploadFilesToOss } from "@/api/upload.js";
import { uploadFormDataToOss } from "@/api/upload.js";

/** 普通官方相册图 */
const OFFICIAL_IMG_TYPE_ALBUM = 2;
/** 环境 Tab 及约定走环境图类型的相册 Tab（如 id=182） */
const OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM = 4;

/** 相册 Tab 的 name 为相册 id 字符串；列入此集合的 Tab 拉列表、保存时 imgType 均为 4 */
const albumTabNamesWithImgType4 = new Set<string>(["182"]);

const isAlbumTabImgType4 = (tabKey: string) => albumTabNamesWithImgType4.has(String(tabKey));

// 扩展图片类型
interface AlbumImage extends UploadUserFile {
  isCover?: boolean;
  businessId?: number; // 相册ID
  imgSort?: number; // 排序
  imgType?: number; // 相册默认 2；环境 / 特殊相册 Tab 为 4
  imgId?: number; // 图片ID（从服务器返回）
}

// 扩展视频类型
interface AlbumVideo extends UploadUserFile {
  businessId?: number; // 相册ID（接口 businessId）
  imgSort?: number; // 排序
  imgType?: number; // 视频类型，可能是3或其他值
  imgId?: number; // 视频ID（从服务器返回）
  videoDuration?: number; // 视频时长（秒）
  coverUrl?: string; // 封面：接口 imgUrl 为 JSON 字符串时的 cover 字段
  imgDescription?: string; // 接口说明文案
}

// 相册接口（getOfficialAlbumList：isFixed 为「视频」时该 Tab 走视频上传与 alienStore/video 列表）
interface Album {
  id: string | number;
  name: string;
  albumName?: string; // API返回的字段名
  isFixed?: string | number | boolean;
  images: AlbumImage[];
  videos: AlbumVideo[];
  coverImageId?: string | number;
}

/** 是否视频相册：与后端 isFixed 约定，支持文案「视频」或数字 1 */
const albumIsVideoAlbum = (a: Album | null | undefined): boolean => {
  if (!a) return false;
  const v = a.isFixed;
  if (v === undefined || v === null) return false;
  if (typeof v === "string") {
    const t = v.trim();
    return t === "视频" || /^video$/i.test(t);
  }
  if (typeof v === "number") {
    return v === 1;
  }
  return v === true;
};

const createDialogVisible = ref(false);
const createFormRef = ref<FormInstance>();
// 环境 / 视频 / 相册 id（字符串）；初始为空，相册列表加载后默认选中第一项
const activeTab = ref("");
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewVideoUrl = ref("");
const editId = ref<string | number | null>(null);

// 正在保存的图片URL集合，防止重复保存
const savingImages = ref<Set<string>>(new Set());
// 已处理过的图片URL集合，防止重复处理
const processedImages = ref<Set<string>>(new Set());
// 是否正在加载相册图片（用于跳过watch触发）
const isLoadingAlbumImages = ref(false);

// 相册列表
const albumList = ref<Album[]>([]);

// 当前是否为相册 Tab（动态相册列表中的某一项）
const isAlbumTab = computed(() => albumList.value.some(album => String(album.id) === activeTab.value));

// 当前选中的相册或环境数据
const currentAlbum = computed(() => {
  // 如果是环境tab，返回环境数据（使用特殊ID）
  if (activeTab.value === "environment") {
    return { id: "environment", name: "环境", images: environmentImages.value, videos: [] };
  }
  // 如果是视频tab，返回视频数据（使用特殊ID）
  if (activeTab.value === "video") {
    return { id: "video", name: "视频", images: [], videos: videoList.value };
  }
  // 否则是相册tab，查找对应的相册
  const album = albumList.value.find(album => String(album.id) === activeTab.value);
  if (album) {
    if (!album.videos) {
      album.videos = [];
    }
    return album;
  }
  return { id: "", name: "", images: [], videos: [] };
});

// 环境图片列表（独立的，不属于任何相册）
const environmentImages = ref<AlbumImage[]>([]);

// 视频列表（独立的，不属于任何相册）
const videoList = ref<AlbumVideo[]>([]);

// 当前相册的引用（用于直接绑定，确保响应式更新）
const currentAlbumRef = computed(() => {
  if (activeTab.value === "environment") {
    return null; // 环境tab使用单独的绑定
  }
  const album = albumList.value.find(album => String(album.id) === activeTab.value);
  if (album) {
    if (!album.images) {
      album.images = reactive<AlbumImage[]>([]);
    }
    if (!album.videos) {
      album.videos = reactive<AlbumVideo[]>([]);
    }
    return album;
  }
  return null;
});

// 当前选中的相册是否为「视频」类型（由 getOfficialAlbumList.isFixed 决定）
const currentAlbumIsVideo = computed(() => albumIsVideoAlbum(currentAlbumRef.value));

// 分页数据
const pageable = reactive({
  pageNum: 1,
  pageSize: 10,
  total: 0
});

// 图片相册：分页后的图片列表
const displayImages = computed(() => {
  if (!isAlbumTab.value || currentAlbumIsVideo.value) {
    return [];
  }
  const images = currentAlbumRef.value?.images || [];
  if (images.length === 0) {
    return [];
  }
  const start = (pageable.pageNum - 1) * pageable.pageSize;
  const end = start + pageable.pageSize;
  return images.slice(start, end);
});

// 显示视频列表（分页后）：独立「视频」Tab 或 isFixed 为视频的相册 Tab
const displayVideos = computed(() => {
  let videos: AlbumVideo[] = [];
  if (activeTab.value === "video") {
    videos = videoList.value || [];
  } else if (isAlbumTab.value && currentAlbumIsVideo.value) {
    videos = currentAlbumRef.value?.videos || [];
  } else {
    return [];
  }

  if (videos.length === 0) {
    return [];
  }

  const start = (pageable.pageNum - 1) * pageable.pageSize;
  const end = start + pageable.pageSize;
  return videos.slice(start, end);
});

const isFirstImage = (displayIndex: number): boolean => {
  const actualIndex = (pageable.pageNum - 1) * pageable.pageSize + displayIndex;
  return actualIndex === 0;
};

// 新建相册表单
const createForm = reactive({
  name: ""
});

// 新建相册表单校验规则
const createRules = reactive<FormRules>({
  name: [
    { required: true, message: "请输入相册名称", trigger: "blur" },
    { min: 1, max: 6, message: "相册名称长度在1到6个字符", trigger: "blur" }
  ]
});

// 图片尺寸校验函数（不小于500像素）
const validateImageDimensions = (file: File): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e: ProgressEvent<FileReader>) => {
      const img = new Image();
      img.onload = () => {
        const width = img.width;
        const height = img.height;

        // 检查尺寸：不小于500像素
        if (width < 500 || height < 500) {
          ElMessage.warning("照片宽高不小于500像素");
          reject(new Error("图片尺寸不符合要求"));
          return;
        }

        resolve(true);
      };
      img.onerror = () => {
        reject(new Error("图片加载失败"));
      };
      if (e.target?.result) {
        img.src = e.target.result as string;
      }
    };
    reader.onerror = () => {
      reject(new Error("文件读取失败"));
    };
    reader.readAsDataURL(file);
  });
};

// 自定义图片上传 API（OSS 直传）
const customImageUploadApi = async (formData: FormData): Promise<any> => {
  const raw = formData.get("file");
  const file = raw instanceof File ? raw : null;
  if (!file) {
    throw new Error("请选择文件");
  }

  try {
    await validateImageDimensions(file);
  } catch (error) {
    throw error;
  }

  const urls = await uploadFilesToOss(file, "image");
  const fileUrl = urls[0];
  if (!fileUrl) {
    throw new Error("上传失败，未返回地址");
  }

  const response = {
    data: { fileUrl },
    fileUrl
  };
  await nextTick();
  return response;
};

/**
 * 阿里云 OSS 等支持 x-oss-process 时，用视频快照作封面（与商家端 albumDetail getOssVideoCoverUrl 一致）
 */
function tryOssVideoSnapshotCoverUrl(videoUrl: string): string {
  if (!videoUrl || typeof videoUrl !== "string") return "";
  if (/upload\.ailien\.shop/i.test(videoUrl)) return "";
  const isOss =
    videoUrl.includes("aliyuncs.com") ||
    videoUrl.includes("oss-cn-") ||
    videoUrl.includes("oss.") ||
    /ailien\.shop/i.test(videoUrl) ||
    videoUrl.includes("alien-volume");
  if (!isOss) return "";
  const sep = videoUrl.includes("?") ? "&" : "?";
  return `${videoUrl}${sep}x-oss-process=video/snapshot,t_0,f_jpg,w_800,h_600,m_fast`;
}

/** 本地视频 File：canvas 截取首帧为 JPEG Blob */
function captureVideoFileFirstFrameAsJpegBlob(videoFile: File): Promise<Blob | null> {
  return new Promise(resolve => {
    const video = document.createElement("video");
    video.muted = true;
    video.playsInline = true;
    video.setAttribute("playsinline", "true");
    video.preload = "metadata";
    const objectUrl = URL.createObjectURL(videoFile);
    let settled = false;
    const finish = (blob: Blob | null) => {
      if (settled) return;
      settled = true;
      URL.revokeObjectURL(objectUrl);
      resolve(blob);
    };

    const grabFrame = () => {
      try {
        const w = video.videoWidth;
        const h = video.videoHeight;
        if (!w || !h) {
          finish(null);
          return;
        }
        const canvas = document.createElement("canvas");
        canvas.width = w;
        canvas.height = h;
        const ctx = canvas.getContext("2d");
        if (!ctx) {
          finish(null);
          return;
        }
        ctx.drawImage(video, 0, 0, w, h);
        canvas.toBlob(b => finish(b), "image/jpeg", 0.88);
      } catch {
        finish(null);
      }
    };

    video.onerror = () => finish(null);

    video.onloadedmetadata = () => {
      const t =
        Number.isFinite(video.duration) && video.duration > 0 ? Math.min(0.1, Math.max(0.01, video.duration * 0.001)) : 0.01;
      try {
        video.currentTime = t;
      } catch {
        finish(null);
      }
    };

    video.onseeked = () => {
      grabFrame();
    };

    video.src = objectUrl;
  });
}

/** 为 saveOrSaveBatch 准备 cover：已有 coverUrl → OSS 快照 → 本地文件首帧上传 */
async function resolveVideoCoverUrlForSave(targetVideo: AlbumVideo, videoUrl: string): Promise<string> {
  const existing = typeof targetVideo.coverUrl === "string" && targetVideo.coverUrl.trim();
  if (existing) return existing;

  const ossCover = tryOssVideoSnapshotCoverUrl(videoUrl);
  if (ossCover) {
    targetVideo.coverUrl = ossCover;
    return ossCover;
  }

  const raw = targetVideo.raw;
  if (raw instanceof File && String(raw.type || "").startsWith("video/")) {
    const blob = await captureVideoFileFirstFrameAsJpegBlob(raw);
    if (blob && blob.size > 0) {
      const coverFile = new File([blob], `video_cover_${Date.now()}.jpg`, { type: "image/jpeg" });
      try {
        const urls = await uploadFilesToOss(coverFile, "image");
        const u = urls[0];
        if (u) {
          targetVideo.coverUrl = u;
          return u;
        }
      } catch (e) {
        console.warn("[officialPhotoAlbum] 封面上传失败", e);
      }
    }
  }

  return "";
}

// 检测视频时长的辅助函数
const getVideoDuration = (file: File): Promise<number> => {
  return new Promise(resolve => {
    if (!file.type.startsWith("video/")) {
      resolve(0);
      return;
    }

    const video = document.createElement("video");
    video.preload = "metadata";

    video.onloadedmetadata = () => {
      window.URL.revokeObjectURL(video.src);
      const duration = Math.floor(video.duration);
      resolve(duration);
    };

    video.onerror = () => {
      window.URL.revokeObjectURL(video.src);
      resolve(0);
    };

    video.src = URL.createObjectURL(file);
  });
};

// 视频上传成功回调，用于保存视频时长
const handleVideoUploadSuccess = async (url: string) => {
  const list: AlbumVideo[] =
    activeTab.value === "video"
      ? videoList.value
      : currentAlbumRef.value && albumIsVideoAlbum(currentAlbumRef.value)
        ? currentAlbumRef.value.videos || []
        : [];
  const video = list.find((v: AlbumVideo) => v.url === url && !v.videoDuration);
  if (!video || !video.raw) {
    return;
  }

  // 检测视频时长
  try {
    const duration = await getVideoDuration(video.raw as File);
    if (duration > 0) {
      video.videoDuration = duration;
    }
  } catch (error) {
    console.error("获取视频时长失败:", error);
  }
};

// 自定义视频上传：与 @/api/upload.js 约定一致，走 Tus +（可选）视频审核，勿用 dev-simple 端点（易仅支持图或未配置导致失败）
const customVideoUploadApi = async (formData: FormData): Promise<any> => {
  const raw = formData.get("file");
  const file = raw instanceof File ? raw : null;
  if (!file) {
    throw new Error("请选择文件");
  }

  const fileSizeMB = file.size / 1024 / 1024;
  if (fileSizeMB > 50) {
    ElMessage.warning(`视频大小不能超过 50MB，当前为 ${fileSizeMB.toFixed(2)}MB`);
    throw new Error("视频大小超过限制");
  }

  const { data } = await uploadFormDataToOss(formData, "video");
  const fileUrl = data?.fileUrl;
  if (!fileUrl) {
    throw new Error("上传失败，未返回地址");
  }

  const response = {
    data: { fileUrl },
    fileUrl
  };
  await nextTick();
  return response;
};

// 保存图片到服务器
const saveImageToServer = async (imgUrl: string) => {
  // 如果正在保存，直接返回，防止重复保存
  if (savingImages.value.has(imgUrl)) {
    return;
  }

  try {
    const userInfo: any = localGet("geeker-user")?.userInfo || {};
    const storeId = userInfo.storeId;
    if (!storeId) {
      return;
    }

    // 判断是环境图片还是相册图片
    let businessId: number;
    let currentImages: AlbumImage[];

    if (activeTab.value === "environment") {
      // 环境图片：使用 storeId 作为 businessId（需要根据实际API调整）
      businessId = Number(storeId);
      currentImages = environmentImages.value || [];
    } else {
      // 相册图片：仅非视频相册（isFixed 非视频）
      if (!currentAlbumRef.value || albumIsVideoAlbum(currentAlbumRef.value)) {
        return;
      }
      businessId = Number(currentAlbumRef.value.id);
      currentImages = currentAlbumRef.value.images || [];
    }

    // 找到对应的图片（通过URL匹配）
    const targetImage = currentImages.find((img: AlbumImage) => img.url === imgUrl && !img.imgId);
    if (!targetImage) {
      return; // 如果图片已经有ID或找不到，不重复保存
    }

    // 标记为正在保存
    savingImages.value.add(imgUrl);

    const imgSort = currentImages.filter((img: AlbumImage) => img.imgId).length + 1; // 排序为已保存图片数量+1

    const imgType =
      activeTab.value === "environment" || isAlbumTabImgType4(activeTab.value)
        ? OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM
        : OFFICIAL_IMG_TYPE_ALBUM;

    const params = [
      {
        businessId: businessId,
        imgSort: imgSort,
        imgType,
        imgUrl: imgUrl,
        storeId: Number(storeId)
      }
    ];

    const res: any = await saveOfficialImg(params);
    if (res && (res.code === 200 || res.code === "200") && res.data && res.data[0]) {
      // 保存成功后，更新图片的ID和其他信息
      targetImage.imgId = res.data[0].id;
      targetImage.businessId = res.data[0].businessId;
      targetImage.imgSort = res.data[0].imgSort;
      // 保存成功后，从已处理集合中移除，允许后续更新
      processedImages.value.delete(imgUrl);
    }
  } catch (error) {
    console.error("保存图片信息失败:", error);
    // 保存失败时，也从已处理集合中移除，允许重试
    processedImages.value.delete(imgUrl);
  } finally {
    // 无论成功或失败，都移除保存标记
    savingImages.value.delete(imgUrl);
  }
};

/** saveOrSaveBatch 返回的 data 可能是数组、list、records 或单条对象 */
function pickFirstRowFromVideoSaveResponse(res: any): Record<string, any> | null {
  const d = res?.data;
  if (d == null) return null;
  if (Array.isArray(d)) return (d[0] as Record<string, any>) ?? null;
  if (typeof d === "object") {
    const o = d as Record<string, any>;
    if (Array.isArray(o.list) && o.list.length) return o.list[0] as Record<string, any>;
    if (Array.isArray(o.records) && o.records.length) return o.records[0] as Record<string, any>;
    if (o.id != null || o.imgUrl != null || o.videoUrl != null || o.url != null) return o;
  }
  return null;
}

/**
 * 解析接口 `imgUrl`：
 * - 若为对象或 JSON 字符串：`cover` = 封面图 URL，`video` = 视频 URL（与 getByStoreId / save 返回一致）
 * - 若为普通字符串：视为单一视频直链，无封面
 * - 支持外层多套 JSON 字符串引号包裹（多次序列化）
 */
function parseOfficialVideoImgUrlField(imgUrlField: unknown): { videoUrl: string; coverUrl: string } {
  if (imgUrlField == null || imgUrlField === "") {
    return { videoUrl: "", coverUrl: "" };
  }
  if (typeof imgUrlField === "object" && imgUrlField !== null) {
    const o = imgUrlField as Record<string, unknown>;
    return {
      videoUrl: String(o.video ?? o.videoUrl ?? o.url ?? ""),
      coverUrl: String(o.cover ?? o.coverUrl ?? o.poster ?? "")
    };
  }
  if (typeof imgUrlField === "string") {
    let s = imgUrlField.trim();
    for (let i = 0; i < 5; i++) {
      if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
        try {
          const next = JSON.parse(s);
          if (typeof next === "string") {
            s = next.trim();
            continue;
          }
        } catch {
          break;
        }
      }
      break;
    }
    if (s.startsWith("{")) {
      try {
        const o = JSON.parse(s) as Record<string, unknown>;
        if (o && typeof o === "object") {
          let videoUrl = String(o.video ?? o.videoUrl ?? o.url ?? "").trim();
          let coverUrl = String(o.cover ?? o.coverUrl ?? o.poster ?? "").trim();
          if (videoUrl.startsWith("{")) {
            try {
              const o2 = JSON.parse(videoUrl) as Record<string, unknown>;
              videoUrl = String(o2.video ?? o2.videoUrl ?? o2.url ?? "").trim();
              if (!coverUrl) {
                coverUrl = String(o2.cover ?? o2.coverUrl ?? o2.poster ?? "").trim();
              }
            } catch {
              /* ignore */
            }
          }
          return { videoUrl, coverUrl };
        }
      } catch {
        /* 非 JSON 则当作直链 */
      }
    }
    return { videoUrl: s, coverUrl: "" };
  }
  return { videoUrl: "", coverUrl: "" };
}

// 保存视频到服务器
const saveVideoToServer = async (videoUrl: string) => {
  // 如果正在保存，直接返回，防止重复保存
  if (savingImages.value.has(videoUrl)) {
    return;
  }

  try {
    const userInfo: any = localGet("geeker-user")?.userInfo || {};
    const storeId = userInfo.storeId;
    if (!storeId) {
      return;
    }

    let currentVideos: AlbumVideo[];
    let businessId: number;

    if (activeTab.value === "video") {
      currentVideos = videoList.value || [];
      businessId = Number(storeId);
    } else if (currentAlbumRef.value && albumIsVideoAlbum(currentAlbumRef.value)) {
      currentVideos = currentAlbumRef.value.videos || [];
      businessId = Number(currentAlbumRef.value.id);
    } else {
      return;
    }
    // 找到对应的视频（通过URL匹配）
    const targetVideo = currentVideos.find((video: AlbumVideo) => video.url === videoUrl && !video.imgId);
    if (!targetVideo) {
      return; // 如果视频已经有ID或找不到，不重复保存
    }

    // 标记为正在保存
    savingImages.value.add(videoUrl);

    const cover = await resolveVideoCoverUrlForSave(targetVideo, videoUrl);

    const params = {
      videoUrls: [videoUrl],
      videoIds: [targetVideo.imgId != null ? targetVideo.imgId : null],
      coverUrls: [cover],
      storeId: Number(storeId),
      businessId
    };

    const res: any = await saveOfficialVideoSaveOrSaveBatch(params);
    const row = pickFirstRowFromVideoSaveResponse(res);
    if (res && (res.code === 200 || res.code === "200")) {
      if (row) {
        targetVideo.imgId = row.id ?? row.videoId ?? targetVideo.imgId;
        targetVideo.businessId = row.businessId ?? businessId;
        targetVideo.imgSort = row.imgSort ?? row.sort;
        const rawImgUrl = row.imgUrl ?? row.img_url;
        const parsed = parseOfficialVideoImgUrlField(rawImgUrl != null ? rawImgUrl : row);
        if (parsed.videoUrl) {
          targetVideo.url = parsed.videoUrl;
        }
        if (parsed.coverUrl) {
          targetVideo.coverUrl = parsed.coverUrl;
        }
      }
      processedImages.value.delete(videoUrl);
    }
  } catch (error) {
    console.error("保存视频信息失败:", error);
    // 保存失败时，也从已处理集合中移除，允许重试
    processedImages.value.delete(videoUrl);
  } finally {
    // 无论成功或失败，都移除保存标记
    savingImages.value.delete(videoUrl);
  }
};

// 打开新建相册弹窗
const openCreateDialog = () => {
  editId.value = null;
  createDialogVisible.value = true;
  resetCreateForm();
};

// 重置新建表单
const resetCreateForm = () => {
  createForm.name = "";
  editId.value = null;
  createFormRef.value?.clearValidate();
};

// 创建/更新相册
const handleCreateAlbum = async () => {
  if (!createFormRef.value) return;

  try {
    await createFormRef.value.validate();
  } catch (error) {
    return;
  }

  if (!createForm.name.trim()) {
    ElMessage.warning("请输入相册名称");
    return;
  }

  try {
    const userInfo: any = localGet("geeker-user")?.userInfo || {};
    const storeId = userInfo.storeId;
    if (!storeId) {
      ElMessage.error("未找到店铺ID");
      return;
    }

    const params: any = {
      albumName: createForm.name.trim(),
      storeId: Number(storeId)
    };

    if (editId.value) {
      params.id = editId.value;
    }

    const res: any = await createOrUpdateOfficialAlbum(params);
    if (res && (res.code === 200 || res.code === "200")) {
      ElMessage.success(editId.value ? "修改相册成功" : "新建相册成功");
      createDialogVisible.value = false;

      // 保存当前选中的相册ID
      const currentAlbumId = activeTab.value;

      resetCreateForm();
      await getAlbumList();

      // 如果是编辑相册，重新加载当前相册的图片
      if (editId.value && currentAlbumId) {
        activeTab.value = currentAlbumId;
        await loadAlbumImages(currentAlbumId);
      } else if (!editId.value && albumList.value.length > 0) {
        // 如果是新建相册，切换到新创建的相册并加载图片
        const newAlbum = albumList.value[albumList.value.length - 1];
        activeTab.value = String(newAlbum.id);
        await loadAlbumImages(String(newAlbum.id));
      }
    } else {
      ElMessage.error(res?.msg || (editId.value ? "修改相册失败" : "新建相册失败"));
    }
  } catch (error: any) {
    console.error("保存相册失败:", error);
    ElMessage.error(error?.msg || "操作失败，请重试");
  }
};

// Tab 切换（环境/视频/相册）
const handleTabClick = async (tab: any) => {
  const tabName = tab.props.name;
  // 如果已经是当前tab，不重复加载
  if (activeTab.value === tabName) {
    return;
  }
  activeTab.value = tabName;
  pageable.pageNum = 1;

  // 根据tab类型加载数据（watch 会处理加载，这里只更新分页）
  await nextTick();
  updatePagination();
};

// 编辑相册
const handleEditAlbum = (album?: Album) => {
  const targetAlbum = album || albumList.value.find(album => String(album.id) === activeTab.value);
  if (!targetAlbum) {
    ElMessage.warning("请先选择要编辑的相册");
    return;
  }
  editId.value = targetAlbum.id;
  createForm.name = targetAlbum.name || targetAlbum.albumName || "";
  createDialogVisible.value = true;
  createFormRef.value?.clearValidate();
};

// 删除相册
const handleDeleteAlbum = async () => {
  if (!editId.value) {
    return;
  }

  try {
    await ElMessageBox.confirm("确认删除该相册吗？删除后相册内的图片或视频也将一并删除。", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    });

    // 找到要删除的相册
    const albumToDelete = albumList.value.find(album => album.id === editId.value);
    if (!albumToDelete) {
      ElMessage.error("未找到要删除的相册");
      return;
    }

    // 调用删除接口
    const res: any = await deleteOfficialAlbum([albumToDelete]);
    if (res && (res.code === 200 || res.code === "200")) {
      ElMessage.success("删除相册成功");
      createDialogVisible.value = false;
      resetCreateForm();

      // 重新获取相册列表（当前 tab 若已不存在会自动选中第一项或清空）
      await getAlbumList();
    } else {
      ElMessage.error(res?.msg || "删除相册失败");
    }
  } catch (error: any) {
    if (error !== "cancel") {
      console.error("删除相册失败:", error);
      ElMessage.error(error?.msg || "删除失败，请重试");
    }
  }
};

// 查看图片
const viewImage = (url: string) => {
  previewImageUrl.value = url;
  previewVisible.value = true;
};

// 查看视频
const viewVideo = (url: string) => {
  previewVideoUrl.value = url;
  previewVisible.value = true;
};

// 删除图片
const deleteImage = async (index: number) => {
  const actualIndex = (pageable.pageNum - 1) * pageable.pageSize + index;

  // 根据当前tab获取对应的图片列表
  let imageList: AlbumImage[];
  if (activeTab.value === "environment") {
    imageList = environmentImages.value;
  } else {
    imageList = currentAlbumRef.value?.images || [];
  }

  const image = imageList[actualIndex] as AlbumImage;
  if (!image) {
    return;
  }

  try {
    // 如果图片有ID，说明已保存到服务器，需要调用删除接口
    if (image.imgId) {
      // 调用删除接口，参数是图片ID数组
      const params = [image.imgId];

      const res: any = await deleteOfficialImg(params);
      if (res && (res.code === 200 || res.code === "200")) {
        imageList.splice(actualIndex, 1);
        updatePagination();
        ElMessage.success("删除成功");
      } else {
        ElMessage.error(res?.msg || "删除失败");
      }
    } else {
      // 如果图片还没有保存到服务器，直接删除本地数据
      imageList.splice(actualIndex, 1);
      updatePagination();
      ElMessage.success("删除成功");
    }
  } catch (error: any) {
    console.error("删除图片失败:", error);
    ElMessage.error(error?.msg || "删除失败，请重试");
  }
};

// 删除视频
const deleteVideo = async (index: number) => {
  const actualIndex = (pageable.pageNum - 1) * pageable.pageSize + index;
  const list: AlbumVideo[] =
    activeTab.value === "video"
      ? videoList.value
      : currentAlbumRef.value && albumIsVideoAlbum(currentAlbumRef.value)
        ? currentAlbumRef.value.videos || []
        : [];
  const video = list[actualIndex] as AlbumVideo;
  if (!video) {
    return;
  }

  try {
    // 如果视频有ID，说明已保存到服务器，需要调用删除接口
    if (video.imgId) {
      // 调用删除接口，参数是视频ID数组
      const params = [video.imgId];

      const res: any = await deleteOfficialImg(params);
      if (res && (res.code === 200 || res.code === "200")) {
        list.splice(actualIndex, 1);
        updatePagination();
        ElMessage.success("删除成功");
      } else {
        ElMessage.error(res?.msg || "删除失败");
      }
    } else {
      // 如果视频还没有保存到服务器，直接删除本地数据
      list.splice(actualIndex, 1);
      updatePagination();
      ElMessage.success("删除成功");
    }
  } catch (error: any) {
    console.error("删除视频失败:", error);
    ElMessage.error(error?.msg || "删除失败，请重试");
  }
};

// 更新分页总数
const updatePagination = () => {
  if (activeTab.value === "video") {
    pageable.total = videoList.value?.length || 0;
  } else if (activeTab.value === "environment") {
    pageable.total = environmentImages.value?.length || 0;
  } else if (isAlbumTab.value) {
    pageable.total = currentAlbumIsVideo.value
      ? currentAlbumRef.value?.videos?.length || 0
      : currentAlbumRef.value?.images?.length || 0;
  } else {
    pageable.total = 0;
  }
};

// 分页大小改变
const handleSizeChange = (size: number) => {
  pageable.pageSize = size;
  pageable.pageNum = 1;
};

// 当前页改变
const handleCurrentChange = (page: number) => {
  pageable.pageNum = page;
};

// 监听环境 Tab 或「图片相册」Tab 的图片列表
watch(
  () => {
    if (activeTab.value === "environment") {
      return environmentImages.value || [];
    }
    if (isAlbumTab.value && currentAlbumRef.value && !albumIsVideoAlbum(currentAlbumRef.value)) {
      return currentAlbumRef.value.images || [];
    }
    return [];
  },
  async (newImages, oldImages) => {
    const isImageAlbumTab = isAlbumTab.value && currentAlbumRef.value && !albumIsVideoAlbum(currentAlbumRef.value);
    if (activeTab.value !== "environment" && !isImageAlbumTab) {
      return;
    }

    updatePagination();

    // 如果正在加载图片（从服务器加载），跳过处理，避免重复保存
    if (isLoadingAlbumImages.value) {
      return;
    }

    // 找出真正新增的图片（通过对比URL）
    const oldUrls = new Set((oldImages || []).map((img: AlbumImage) => img.url).filter((url): url is string => Boolean(url)));
    const newUrls = new Set((newImages || []).map((img: AlbumImage) => img.url).filter((url): url is string => Boolean(url)));

    // 找出新增的URL（在新列表中存在，但在旧列表中不存在）
    const addedUrls = Array.from(newUrls).filter(url => !oldUrls.has(url));

    // 处理新增的图片：没有imgId、有url、且未处理过、且不在保存中的图片
    // 批量处理所有新增的图片
    const imagesToSave = addedUrls
      .map(url => newImages.find((img: AlbumImage) => img.url === url))
      .filter((image): image is AlbumImage => {
        return (
          image !== undefined &&
          !image.imgId &&
          image.url !== undefined &&
          image.url !== null &&
          image.url !== "" &&
          !savingImages.value.has(image.url) &&
          !processedImages.value.has(image.url)
        );
      });

    // 并发保存所有新上传的图片
    for (const image of imagesToSave) {
      const imageUrl = image.url;
      if (imageUrl) {
        // 标记为已处理，防止重复处理
        processedImages.value.add(imageUrl);
        // 不等待，让所有图片并发上传
        saveImageToServer(imageUrl).catch(error => {
          console.error("保存图片失败:", error);
          // 保存失败时，从已处理集合中移除，允许重试
          processedImages.value.delete(imageUrl);
        });
      }
    }
  },
  { deep: true }
);

// 监听视频列表：独立「视频」Tab 或 isFixed 为视频的相册 Tab
watch(
  () => {
    if (activeTab.value === "video") {
      return videoList.value || [];
    }
    if (isAlbumTab.value && currentAlbumRef.value && albumIsVideoAlbum(currentAlbumRef.value)) {
      return currentAlbumRef.value.videos || [];
    }
    return [];
  },
  async (newVideos, oldVideos) => {
    const isVideoAlbumTab = isAlbumTab.value && currentAlbumRef.value && albumIsVideoAlbum(currentAlbumRef.value);
    if (activeTab.value !== "video" && !isVideoAlbumTab) {
      return;
    }

    updatePagination();

    // 如果正在加载视频（从服务器加载），跳过处理，避免重复保存
    if (isLoadingAlbumImages.value) {
      return;
    }

    // 找出真正新增的视频（通过对比URL）
    const oldUrls = new Set((oldVideos || []).map((video: AlbumVideo) => video.url).filter((url): url is string => Boolean(url)));
    const newUrls = new Set((newVideos || []).map((video: AlbumVideo) => video.url).filter((url): url is string => Boolean(url)));

    // 找出新增的URL（在新列表中存在，但在旧列表中不存在）
    const addedUrls = Array.from(newUrls).filter(url => !oldUrls.has(url));

    // 处理新增的视频：没有imgId、有url、且未处理过、且不在保存中的视频
    const videosToSave = addedUrls
      .map(url => newVideos.find((video: AlbumVideo) => video.url === url))
      .filter((video): video is AlbumVideo => {
        return (
          video !== undefined &&
          !video.imgId &&
          video.url !== undefined &&
          video.url !== null &&
          video.url !== "" &&
          !savingImages.value.has(video.url) &&
          !processedImages.value.has(video.url)
        );
      });

    // 并发保存所有新上传的视频
    for (const video of videosToSave) {
      const videoUrl = video.url;
      if (videoUrl) {
        // 如果视频还没有时长，尝试获取
        if (!video.videoDuration && video.raw) {
          try {
            const duration = await getVideoDuration(video.raw as File);
            if (duration > 0) {
              video.videoDuration = duration;
            }
          } catch (error) {
            console.error("获取视频时长失败:", error);
          }
        }

        // 标记为已处理，防止重复处理
        processedImages.value.add(videoUrl);
        // 不等待，让所有视频并发上传
        saveVideoToServer(videoUrl).catch(error => {
          console.error("保存视频失败:", error);
          // 保存失败时，从已处理集合中移除，允许重试
          processedImages.value.delete(videoUrl);
        });
      }
    }
  },
  { deep: true }
);

// 监听tab切换，加载对应的数据
watch(
  () => activeTab.value,
  async (newVal, oldVal) => {
    // 如果tab没有变化，不重复加载
    if (newVal === oldVal) {
      return;
    }
    // 重置分页到第一页
    pageable.pageNum = 1;

    // 根据tab类型加载数据
    if (newVal === "environment") {
      await loadEnvironmentImages();
    } else if (newVal === "video") {
      await loadVideoList();
    } else if (newVal) {
      // 相册tab
      await loadAlbumImages(newVal);
    }
    // 注意：updatePagination 在各自的 load 函数中已调用
  }
);

// 获取相册列表
const getAlbumList = async () => {
  try {
    const userInfo: any = localGet("geeker-user")?.userInfo || {};
    const storeId = userInfo.storeId;
    if (!storeId) {
      console.warn("未找到店铺ID");
      return;
    }

    const params = {
      storeId: Number(storeId)
    };
    const res: any = await getOfficialAlbumList(params);
    if (res && (res.code === 200 || res.code === "200") && res.data) {
      const dataList = Array.isArray(res.data) ? res.data : [];
      albumList.value = dataList.map((album: any) => ({
        id: album.id,
        name: album.albumName || album.name,
        albumName: album.albumName,
        isFixed: album.isFixed,
        images: reactive<AlbumImage[]>([]), // 使用 reactive 确保响应式
        videos: reactive<AlbumVideo[]>([]),
        coverImageId: album.coverImageId
      }));
      // 默认选中第一个相册；若当前 tab 仍有效则保留（如刷新列表、新建后切到最后一个）
      const prev = activeTab.value;
      const idSet = new Set(albumList.value.map(a => String(a.id)));
      if (albumList.value.length > 0) {
        const keepSpecial = prev === "environment" || prev === "video";
        const keepAlbum = Boolean(prev && idSet.has(String(prev)));
        if (!keepSpecial && !keepAlbum) {
          activeTab.value = String(albumList.value[0].id);
        }
      } else if (prev !== "environment" && prev !== "video") {
        activeTab.value = "";
      }
    }
  } catch (error) {
    console.error("获取相册列表失败:", error);
  }
};

// 加载环境图片列表
const loadEnvironmentImages = async () => {
  try {
    isLoadingAlbumImages.value = true;
    const userInfo: any = localGet("geeker-user")?.userInfo || {};
    const storeId = userInfo.storeId;
    if (!storeId) {
      return;
    }

    // 环境图片：使用 storeId 作为 businessId（需要根据实际API调整）
    // 或者如果环境图片不需要 businessId，可能需要使用其他API
    // 这里先使用 storeId 作为 businessId
    const imageRes: any = await getOfficialImgList(Number(storeId), Number(storeId), OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM);

    if (imageRes && (imageRes.code === 200 || imageRes.code === "200") && imageRes.data) {
      const imageList = Array.isArray(imageRes.data) ? imageRes.data : [];
      const images: AlbumImage[] = imageList
        .filter((img: any) => img.deleteFlag !== 1)
        .map((img: any) => ({
          uid: img.id || Date.now() + Math.random(),
          name: img.imgUrl?.split("/").pop() || "image",
          url: img.imgUrl,
          status: "success",
          imgId: img.id,
          businessId: img.businessId,
          imgSort: img.imgSort,
          imgType: img.imgType,
          isCover: false
        }))
        .sort((a: AlbumImage, b: AlbumImage) => (a.imgSort || 0) - (b.imgSort || 0));
      // 使用数组替换确保响应式更新
      environmentImages.value.splice(0, environmentImages.value.length, ...images);
    } else {
      environmentImages.value.splice(0, environmentImages.value.length);
    }

    processedImages.value.clear();
  } catch (error) {
    console.error("获取环境图片列表失败:", error);
    environmentImages.value.splice(0, environmentImages.value.length);
  } finally {
    isLoadingAlbumImages.value = false;
    await nextTick();
    updatePagination();
  }
};

const parseOfficialVideoListPayload = (payload: any): any[] => {
  if (Array.isArray(payload)) return payload;
  if (payload && Array.isArray(payload.list)) return payload.list;
  if (payload && Array.isArray(payload.records)) return payload.records;
  return [];
};

const mapOfficialVideoRowToAlbumVideo = (video: any): AlbumVideo => {
  const parsed = parseOfficialVideoImgUrlField(video.imgUrl);
  const fallback = video.videoUrl || video.url || video.fileUrl || "";
  const url = (parsed.videoUrl || fallback).trim();
  let coverUrl = (parsed.coverUrl || "").trim();
  if (!coverUrl) {
    coverUrl = String(
      video.cover || video.coverUrl || video.poster || video.thumbnailUrl || video.thumbnail || video.videoCover || ""
    ).trim();
  }
  const id = video.id;
  const desc = video.imgDescription != null ? String(video.imgDescription).trim() : "";
  const name = desc || (url ? url.split("/").pop()?.split("?")[0] || "video" : "video");
  return {
    uid: id || Date.now() + Math.random(),
    name,
    url,
    status: "success",
    imgId: id,
    businessId: video.businessId,
    imgSort: video.imgSort ?? video.sort,
    imgType: video.imgType ?? 3,
    videoDuration: video.videoDuration ?? video.duration ?? 0,
    coverUrl: coverUrl || undefined,
    imgDescription: desc || undefined
  };
};

/** GET /alienStore/video/getByStoreId */
const fetchStoreOfficialVideosRaw = async (storeId: number | string) => {
  const videoRes: any = await getOfficialVideoByStoreId(storeId);
  if (videoRes && (videoRes.code === 200 || videoRes.code === "200") && videoRes.data != null) {
    return parseOfficialVideoListPayload(videoRes.data);
  }
  return [];
};

// 加载视频列表（独立「视频」Tab）
const loadVideoList = async () => {
  try {
    isLoadingAlbumImages.value = true;
    const userInfo: any = localGet("geeker-user")?.userInfo || {};
    const storeId = userInfo.storeId;
    if (!storeId) {
      return;
    }

    const rawList = await fetchStoreOfficialVideosRaw(storeId);
    const videos: AlbumVideo[] = rawList
      .filter((video: any) => video.deleteFlag !== 1)
      .map(mapOfficialVideoRowToAlbumVideo)
      .sort((a: AlbumVideo, b: AlbumVideo) => (a.imgSort || 0) - (b.imgSort || 0));
    videoList.value.splice(0, videoList.value.length, ...videos);

    processedImages.value.clear();
  } catch (error) {
    console.error("获取视频列表失败:", error);
    videoList.value.splice(0, videoList.value.length);
  } finally {
    isLoadingAlbumImages.value = false;
    await nextTick();
    updatePagination();
  }
};

// 图片相册：getOfficialImgList（与改造前一致）
const loadAlbumPicturesForAlbum = async (albumId: string) => {
  const userInfo: any = localGet("geeker-user")?.userInfo || {};
  const storeId = userInfo.storeId;
  if (!storeId || !albumId) {
    return;
  }

  const current = albumList.value.find(album => String(album.id) === albumId);
  if (!current) {
    return;
  }

  const listImgType = isAlbumTabImgType4(albumId) ? OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM : OFFICIAL_IMG_TYPE_ALBUM;
  const imageRes: any = await getOfficialImgList(Number(albumId), Number(storeId), listImgType);

  if (imageRes && (imageRes.code === 200 || imageRes.code === "200") && imageRes.data) {
    const imageList = Array.isArray(imageRes.data) ? imageRes.data : [];
    const images: AlbumImage[] = imageList
      .filter((img: any) => img.deleteFlag !== 1)
      .map((img: any) => ({
        uid: img.id || Date.now() + Math.random(),
        name: img.imgUrl?.split("/").pop() || "image",
        url: img.imgUrl,
        status: "success",
        imgId: img.id,
        businessId: img.businessId,
        imgSort: img.imgSort,
        imgType: img.imgType,
        isCover: false
      }))
      .sort((a: AlbumImage, b: AlbumImage) => (a.imgSort || 0) - (b.imgSort || 0));
    if (!current.images) {
      current.images = reactive<AlbumImage[]>([]);
    }
    current.images.splice(0, current.images.length, ...images);
  } else {
    if (!current.images) {
      current.images = reactive<AlbumImage[]>([]);
    } else {
      current.images.splice(0, current.images.length);
    }
  }

  if (!current.videos) {
    current.videos = reactive<AlbumVideo[]>([]);
  } else {
    current.videos.splice(0, current.videos.length);
  }
};

// 视频相册：getOfficialVideoByStoreId，按 businessId 与相册 id 匹配
const loadAlbumVideosForAlbum = async (albumId: string) => {
  const userInfo: any = localGet("geeker-user")?.userInfo || {};
  const storeId = userInfo.storeId;
  if (!storeId || !albumId) {
    return;
  }

  const current = albumList.value.find(album => String(album.id) === albumId);
  if (!current) {
    return;
  }

  const rawList = await fetchStoreOfficialVideosRaw(storeId);
  const albumKey = String(albumId);
  const forAlbum = rawList.filter((v: any) => {
    if (v.deleteFlag === 1) return false;
    const bid = v.businessId ?? v.albumId ?? v.officialAlbumId;
    return bid != null && String(bid) === albumKey;
  });
  const videos: AlbumVideo[] = forAlbum
    .map(mapOfficialVideoRowToAlbumVideo)
    .sort((a: AlbumVideo, b: AlbumVideo) => (a.imgSort || 0) - (b.imgSort || 0));

  if (!current.videos) {
    current.videos = reactive<AlbumVideo[]>([]);
  }
  current.videos.splice(0, current.videos.length, ...videos);

  if (!current.images) {
    current.images = reactive<AlbumImage[]>([]);
  } else {
    current.images.splice(0, current.images.length);
  }
};

const loadAlbumImages = async (albumId: string) => {
  try {
    isLoadingAlbumImages.value = true;

    const current = albumList.value.find(album => String(album.id) === albumId);
    if (!current) {
      return;
    }

    if (albumIsVideoAlbum(current)) {
      await loadAlbumVideosForAlbum(albumId);
    } else {
      await loadAlbumPicturesForAlbum(albumId);
    }

    processedImages.value.clear();
  } catch (error) {
    console.error("获取相册媒体列表失败:", error);
    const current = albumList.value.find(album => String(album.id) === albumId);
    if (current) {
      processedImages.value.clear();
      if (albumIsVideoAlbum(current)) {
        if (!current.videos) {
          current.videos = reactive<AlbumVideo[]>([]);
        } else {
          current.videos.splice(0, current.videos.length);
        }
      } else {
        if (!current.images) {
          current.images = reactive<AlbumImage[]>([]);
        } else {
          current.images.splice(0, current.images.length);
        }
      }
    }
  } finally {
    isLoadingAlbumImages.value = false;
    await nextTick();
    updatePagination();
  }
};

// 页面初始化：拉相册列表后默认第一项，图片由 watch(activeTab) 加载
onMounted(async () => {
  await getAlbumList();
});
</script>

<style scoped lang="scss">
.photo-album-container {
  position: relative;
  min-height: 100%;
  padding: 20px;
  background-color: white;
  .header-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 24px;
    :deep(.el-tabs) {
      flex: 1;
      .el-tabs__header {
        margin: 0;
      }
    }
    .header-actions {
      display: flex;
      gap: 12px;
      align-items: center;
    }
    .album-tab-label {
      display: inline-flex;
      gap: 8px;
      align-items: center;
      .edit-icon {
        font-size: 14px;
        color: #909399;
        cursor: pointer;
        transition: color 0.3s;
        &:hover {
          color: #409eff;
        }
      }
    }
  }
  .content-section {
    .upload-tips {
      display: flex;
      flex-wrap: wrap;
      gap: 16px;
      margin-bottom: 20px;
      font-size: 14px;
      color: #606266;
    }
    .media-grid {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 16px;
      margin-bottom: 20px;
      .upload-item {
        position: relative;
        width: 100%;
        min-height: 200px;

        // 只隐藏已上传的列表项，保留上传按钮
        :deep(.el-upload-list__item) {
          display: none !important;
        }

        // 确保上传按钮容器正常
        :deep(.upload-box) {
          display: block !important;
          width: 100% !important;
        }

        // 确保上传组件容器正常
        :deep(.upload) {
          display: block !important;
          width: 100% !important;
        }

        // 确保上传列表容器宽度正确
        :deep(.el-upload-list--picture-card) {
          display: block !important;
          width: 100% !important;
        }

        // 确保上传按钮正常显示和可点击，覆盖组件内部的固定宽度
        :deep(.el-upload--picture-card) {
          position: relative !important;
          box-sizing: border-box !important;
          display: inline-block !important;
          width: 100% !important;
          max-width: 100% !important;
          height: 200px !important;
          pointer-events: auto !important;
          cursor: pointer !important;
        }

        // 确保上传输入框覆盖整个按钮区域
        :deep(.el-upload--picture-card .el-upload__input) {
          position: absolute !important;
          top: 0 !important;
          left: 0 !important;
          z-index: 10 !important;
          width: 100% !important;
          height: 100% !important;
          cursor: pointer !important;
          opacity: 0 !important;
        }

        // 确保上传按钮内容不阻挡点击
        :deep(.el-upload--picture-card .upload-empty) {
          position: relative !important;
          z-index: 1 !important;
          pointer-events: none !important;
        }
      }
      .media-item {
        position: relative;
        min-height: 200px;
        .media-wrapper {
          position: relative;
          width: 100%;
          height: 200px;
          overflow: hidden;
          background-color: #f0f0f0;
          border-radius: 8px;
          img,
          .media-preview {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
          .media-cover-thumb {
            position: absolute;
            inset: 0;
            z-index: 1;
            width: 100%;
            height: 100%;
            pointer-events: none;
            object-fit: cover;
            border-radius: 8px;
          }
          .media-placeholder {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            width: 100%;
            height: 100%;
            color: #909399;
            .el-icon {
              margin-bottom: 8px;
              font-size: 48px;
            }
          }
          .media-overlay {
            position: absolute;
            inset: 0;
            z-index: 2;
            display: flex;
            gap: 12px;
            align-items: center;
            justify-content: center;
            background-color: rgb(0 0 0 / 60%);
            opacity: 0;
            transition: opacity 0.3s;
            .el-button {
              color: white;
            }
          }
          &:hover .media-overlay {
            opacity: 1;
          }
          .cover-tag {
            position: absolute;
            top: 8px;
            right: 8px;
          }
        }
      }
    }
  }
  .empty-state {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 400px;
    .empty-text {
      font-size: 16px;
      color: #909399;
    }
  }
  .upload-tip-text {
    margin-top: 8px;
    font-size: 12px;
    color: #909399;
    text-align: center;
  }
  .dialog-footer {
    display: flex;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    .footer-left {
      display: flex;
      gap: 12px;
    }
    .footer-right {
      display: flex;
      gap: 12px;
    }
  }
}
.pagination-section {
  position: absolute;
  right: 40px;
  bottom: 20px;
  z-index: 1000;
  display: flex;
  justify-content: flex-end;
}

// 预览弹窗样式
:deep(.preview-dialog) {
  .el-dialog {
    max-width: 90vw;
    margin: 5vh auto;
  }
  .el-dialog__body {
    max-height: 80vh;
    padding: 20px;
    overflow: auto;
  }
  .preview-content {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
    max-height: 70vh;
    overflow: hidden;
  }
  .preview-image {
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: 70vh;
    object-fit: contain;
  }
  .preview-video {
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: 70vh;
  }
}
</style>
