<template>
  <div class="head-map-container">
    <div class="content-wrapper">
      <!-- 顶部：大图模式预览 -->
      <div class="mode-preview-section">
        <div class="preview-box">
          <div class="preview-card">
            <div class="preview-images-carousel">
              <el-carousel
                v-if="carouselPreviewImages.length > 0"
                height="250px"
                :autoplay="carouselPreviewImages.length > 1"
                :interval="4000"
                indicator-position="none"
                :arrow="carouselPreviewImages.length > 1 ? 'hover' : 'never'"
                class="head-preview-carousel"
              >
                <el-carousel-item v-for="(url, index) in carouselPreviewImages" :key="index">
                  <img :src="url" alt="头图" class="carousel-preview-img" />
                </el-carousel-item>
              </el-carousel>
              <div v-else class="carousel-preview-empty">
                <div class="preview-placeholder">示例图</div>
              </div>
              <div class="overlay-button">
                <span>相册</span>
                <el-icon><ArrowRight /></el-icon>
              </div>
            </div>
            <div class="preview-info">
              <div class="store-name">示例门店</div>
              <div class="store-rating">
                <el-rate v-model="previewData.rating" disabled show-score text-color="#ff9900" score-template="{value}" />
              </div>
              <div class="store-reviews">{{ previewData.reviews }} 条评价</div>
              <el-icon class="arrow-icon">
                <ArrowRight />
              </el-icon>
            </div>
          </div>
          <div class="mode-label">
            <span>大图模式</span>
          </div>
        </div>
      </div>

      <!-- 中间：上传区域 -->
      <div class="upload-section">
        <h2 class="section-title">图片</h2>

        <div class="instructions">
          <ol class="instruction-list">
            <li>图片会在店铺头图区域展示。</li>
            <li>至少上传3张图片,可拖拽排序。</li>
            <li>建议上传16:9尺寸的图片,大小不超过20MB 避免图片出现显示不全问题。</li>
          </ol>
        </div>

        <el-form ref="multipleFormRef" :model="formData" :rules="multipleRules" label-width="0">
          <el-form-item prop="multipleImages">
            <div class="multiple-upload-wrapper" :class="{ 'upload-full': formData.multipleImages.length >= 6 }">
              <UploadImgs
                v-model:file-list="formData.multipleImages"
                :limit="6"
                :file-size="20"
                :file-type="['image/jpeg', 'image/png', 'image/gif', 'image/webp']"
                :width="'200px'"
                :height="'112px'"
                :border-radius="'8px'"
                :api="uploadImageResult"
                :on-success="handleStoreOcrAfterUploadMore"
                :show-success-notification="false"
              >
                <template #tip>
                  <div class="upload-tip">上传图片({{ formData.multipleImages.length }}/6)</div>
                </template>
              </UploadImgs>
            </div>
          </el-form-item>
        </el-form>
      </div>

      <!-- 底部：保存按钮 -->
      <div class="footer">
        <el-button type="primary" size="large" :loading="loading" @click="handleSave"> 保存 </el-button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch, nextTick } from "vue";
import { ElMessage, ElNotification } from "element-plus";
import type { FormInstance, FormRules } from "element-plus";
import type { UploadUserFile } from "element-plus";

/** 服务端图片主键，用于 saveOrUpdateImg 区分更新与新增 */
type HeadMapUploadFile = UploadUserFile & { serverImgId?: number | string };
import { ArrowRight } from "@element-plus/icons-vue";
import Sortable from "sortablejs";
import UploadImgs from "@/components/Upload/Imgs.vue";
import { getStoreOcrData } from "@/api/modules/newLoginApi";
import { uploadFilesToOss } from "@/api/upload.js";
import { getStoreHeadImg, saveStoreHeadImg } from "@/api/modules/storeDecoration";
import { getDetail } from "@/api/modules/homeEntry";
import { localGet } from "@/utils";
import { useRouter } from "vue-router";

const loading = ref(false);
const multipleFormRef = ref<FormInstance>();
const sortableInstance = ref<Sortable | null>(null);
const router = useRouter();
const storeName = ref("");

const handleStoreOcrAfterUploadMore = async (imageUrl: string) => {
  try {
    await handleStoreOcr({ imageUrl });
  } catch (error) {
    formData.multipleImages = formData.multipleImages.filter(item => item.url !== imageUrl);
    throw error;
  }
};

const handleStoreOcr = async (params: { imageUrl: string }) => {
  try {
    const res: any = await getStoreOcrData({ imageUrl: params.imageUrl, merchantName: storeName.value });
    if (res.code === 200) {
      if (res.data.overall_match) {
        ElNotification({
          title: "OCR识别成功",
          message: `识别结果: ${res.msg || "无"}`,
          type: "success",
          duration: 5000
        });
      } else {
        ElNotification({
          title: "OCR识别失败",
          message: "图片不符合规范，请重新上传",
          type: "error",
          duration: 5000
        });
        formData.multipleImages = [];
      }
    } else {
      const errorMsg = res?.msg || "未查询到OCR识别数据";
      ElMessage.error(errorMsg);
      const error = new Error(errorMsg);
      formData.multipleImages = [];
      (error as any).handled = true;
      throw error;
    }
  } catch (error: any) {
    if (!error.handled) {
    }
    throw error;
  }
};

const formData = reactive({
  multipleImages: [] as HeadMapUploadFile[]
});

const previewData = reactive({
  rating: 5.0,
  reviews: 1853
});

/** 预览轮播：展示已上传头图，一次一张 */
const carouselPreviewImages = computed(() => {
  return formData.multipleImages.map(item => item.url || "").filter((url): url is string => Boolean(url));
});

/**
 * OSS 直传：满足 UploadImgs（读 response.fileUrl）
 */
const uploadImageResult = async (payload: FormData): Promise<any> => {
  const raw = payload.get("file");
  const file = raw instanceof File ? raw : null;
  if (!file) {
    throw new Error("请选择文件");
  }
  const isVideo = typeof file.type === "string" && file.type.startsWith("video/");
  const urls = await uploadFilesToOss(file, isVideo ? "video" : "image");
  const url = urls[0];
  if (!url) {
    throw new Error("上传失败，未返回地址");
  }
  return {
    fileUrl: url,
    data: { fileUrl: url }
  };
};

const multipleRules = reactive<FormRules>({
  multipleImages: [
    {
      validator: (rule, value, callback) => {
        if (!value || value.length < 3) {
          callback(new Error("至少上传3张图片"));
        } else {
          callback();
        }
      },
      trigger: "change"
    }
  ]
});

watch(
  () => formData.multipleImages.length,
  () => {
    nextTick(() => {
      initDragSort();
    });
  }
);

const initDragSort = () => {
  if (sortableInstance.value) {
    sortableInstance.value.destroy();
    sortableInstance.value = null;
  }

  const uploadList = document.querySelector(".el-upload-list--picture-card");
  if (!uploadList) return;

  sortableInstance.value = Sortable.create(uploadList as HTMLElement, {
    animation: 300,
    onEnd({ newIndex, oldIndex }) {
      if (newIndex === undefined || oldIndex === undefined) return;
      const newList = [...formData.multipleImages];
      const [removedItem] = newList.splice(oldIndex, 1);
      newList.splice(newIndex, 0, removedItem);
      formData.multipleImages = newList;
    }
  });
};

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

    const res: any = await getStoreHeadImg(storeId, 20);
    if (res && (res.code === 200 || res.code === "200") && res.data) {
      const dataAny = res.data as any;
      const imgList = Array.isArray(dataAny) ? dataAny : dataAny.storeImgList || [];
      if (imgList.length > 0) {
        formData.multipleImages = imgList.map((item: any, index: number) => ({
          uid: item.id != null ? item.id : `loaded-${index}-${Date.now()}`,
          name: `image-${index + 1}`,
          url: item.imgUrl,
          status: "success",
          serverImgId: item.id != null ? item.id : undefined
        }));
        nextTick(() => {
          initDragSort();
        });
      }
    }
  } catch (error) {
    console.error("获取头图失败:", error);
  }
};

const handleDetail = async () => {
  try {
    const param = {
      id: localGet("geeker-user")?.userInfo.storeId
    };
    const res: any = await getDetail(param as any);
    if (res.code == 200) {
      storeName.value = res.data.storeName;
    }
  } catch (error) {
    console.error("未找到用户信息:", error);
  }
};

onMounted(async () => {
  await handleDetail();
  await getStoreHeadImgData();
  nextTick(() => {
    initDragSort();
  });
});

const handleSave = async () => {
  if (!multipleFormRef.value) return;

  const userInfo: any = localGet("geeker-user")?.userInfo || {};
  const storeId = userInfo.storeId;
  if (!storeId) {
    ElMessage.error("未找到店铺ID，请先完成店铺信息填写");
    return;
  }

  loading.value = true;
  try {
    const storeImgList = formData.multipleImages.map((item, index) => {
      const row: Record<string, unknown> = {
        imgType: 20,
        imgUrl: item.url || "",
        imgSort: index + 1,
        storeId: Number(storeId)
      };
      const sid = (item as HeadMapUploadFile).serverImgId;
      if (sid != null && sid !== "") {
        row.id = typeof sid === "string" ? Number(sid) || sid : sid;
      }
      return row;
    });

    const params = {
      imgMode: 1,
      imgType: 20,
      storeId: Number(storeId),
      storeImgList
    };

    const result: any = await saveStoreHeadImg(params);
    if (result && (result.code === 200 || result.code === "200")) {
      ElNotification({
        title: "保存成功",
        type: "success",
        duration: 3000
      });
      router.push("/home/index");
    } else {
      ElMessage.error(result?.msg || "保存失败");
    }
  } catch (error: any) {
    console.error("保存失败:", error);
    ElMessage.error(error?.msg || "保存失败，请重试");
  } finally {
    loading.value = false;
  }
};
</script>

<style scoped lang="scss">
.head-map-container {
  min-height: 100%;
  padding: 20px;
  background-color: white;
  .content-wrapper {
    max-width: 1400px;
    margin: 0 auto;
  }
  .mode-preview-section {
    margin-bottom: 40px;
    .preview-box {
      width: 100%;
      max-width: 560px;
      .preview-card {
        padding: 16px;
        background-color: white;
        border: 2px solid #409eff;
        border-radius: 8px;
        box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
        transition: all 0.3s;
        .preview-images-carousel {
          position: relative;
          width: 100%;
          margin-bottom: 16px;
          overflow: visible;
          background-color: #f0f0f0;
          border-radius: 8px;
          .head-preview-carousel {
            width: 100%;
            :deep(.el-carousel__container) {
              height: 200px;
              border-radius: 8px;
            }
            :deep(.el-carousel__item) {
              display: flex;
              align-items: center;
              justify-content: center;
              overflow: hidden;
              background-color: #e4e7ed;
            }
            :deep(.el-carousel__arrow) {
              background-color: rgb(0 0 0 / 35%);
            }
          }
          .carousel-preview-img {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
          .carousel-preview-empty {
            display: flex;
            align-items: center;
            justify-content: center;
            height: 200px;
            background-color: #e4e7ed;
            border-radius: 8px;
            .preview-placeholder {
              font-size: 12px;
              color: #909399;
            }
          }
          .overlay-button {
            position: absolute;
            right: 12px;
            bottom: 12px;
            z-index: 2;
            display: flex;
            gap: 4px;
            align-items: center;
            padding: 6px 12px;
            font-size: 12px;
            color: white;
            pointer-events: none;
            background-color: rgb(0 0 0 / 60%);
            border-radius: 4px;
          }
        }
        .preview-info {
          position: relative;
          .store-name {
            margin-bottom: 8px;
            font-size: 16px;
            font-weight: bold;
            color: #000000;
          }
          .store-rating {
            display: flex;
            align-items: center;
            margin-bottom: 4px;
            :deep(.el-rate) {
              .el-rate__icon {
                font-size: 14px;
              }
            }
          }
          .store-reviews {
            font-size: 14px;
            color: #606266;
          }
          .arrow-icon {
            position: absolute;
            top: 50%;
            right: 0;
            font-size: 18px;
            color: #909399;
            transform: translateY(-50%);
          }
        }
      }
      .mode-label {
        display: flex;
        gap: 8px;
        align-items: center;
        justify-content: center;
        margin-top: 12px;
        font-size: 14px;
        color: #606266;
        text-align: center;
      }
    }
  }
  .upload-section {
    margin-bottom: 40px;
    .section-title {
      margin-bottom: 20px;
      font-size: 18px;
      font-weight: bold;
      color: #000000;
    }
    .instructions {
      margin-bottom: 24px;
      .instruction-list {
        padding-left: 20px;
        margin: 0;
        font-size: 14px;
        line-height: 24px;
        color: #606266;
        li {
          margin-bottom: 8px;
        }
      }
    }
    .multiple-upload-wrapper {
      display: flex;
      justify-content: center;
      &.upload-full {
        :deep(.el-upload--picture-card) {
          display: none !important;
        }
      }
    }
    .upload-tip {
      margin-top: 12px;
      font-size: 14px;
      color: #909399;
      text-align: center;
    }
  }
  .footer {
    display: flex;
    justify-content: center;
    margin-top: 40px;
  }
}
</style>
