<template>
  <view class="webview-wrapper">
    <!-- 加载状态提示 -->
    <view class="loading-mask" v-if="isLoading">
      <uni-loading-icon type="circle" size="24" color="#333"></uni-loading-icon>
      <text class="loading-txt">加载中...</text>
    </view>

    <web-view
      :src="h5Url"
      id="any-id"
      @load="onWebViewLoad"
      @error="onWebViewError"
      @message="onWebViewMessage"
    ></web-view>
  </view>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { H5_BASE_URL, TOKENNAME, WHITELIST } from "@/config/app";
import { useAppStore } from "@/stores/app";
import { toLogin, checkLogin } from "@/libs/login";

const h5Url = ref("");
const appStore = useAppStore();
const isLoading = ref(true);
const errorMsg = ref("");

onUnmounted(() => {
  isLoading.value = false;
});

onLoad((query) => {
  try {
    const { path = "/", ...otherParams } = query;
    let normalizedPath = normalizeH5Path(path);
    const token = appStore.tokenComputed;

    if (!token && !WHITELIST.includes(normalizedPath)) {
      uni.showToast({
        title: "登录已失效，请重新登录",
        icon: "none",
        duration: 1500,
      });
      setTimeout(() => {
        toLogin();
      }, 1500);
      return;
    }

    if (!normalizedPath) {
      uni.showToast({
        title: "页面路径无效，默认跳转首页",
        icon: "none",
        duration: 1500,
      });
      normalizedPath = "/";
    }

    // 参数处理
    const params = {
      ...parseComplexParams(otherParams),
      [TOKENNAME]: token,
    };

    const queryString = buildQueryString(params);
    console.log(H5_BASE_URL)
    h5Url.value = `${H5_BASE_URL}/#${normalizedPath}${
      queryString ? `?${queryString}` : ""
    }`;
    console.log("WebView 加载地址：", h5Url.value);
  } catch (err) {
    console.error("WebView 初始化失败：", err);
    uni.showToast({ title: "页面加载异常", icon: "none", duration: 1500 });
    setTimeout(() => uni.navigateBack(), 1500);
  }
});

// 标准化H5路径
const normalizeH5Path = (path) => {
  if (typeof path !== "string") {
    console.warn("H5路径格式错误：非字符串类型");
    return null;
  }

  // URL解码
  let decodedPath;
  try {
    decodedPath = decodeURIComponent(path);
  } catch (err) {
    console.error("H5路径解码失败（非法编码格式）：", err, "原始路径：", path);
    return null;
  }

  const purePath = decodedPath.split(/[?#]/)[0];

  const pathReg = /^\/[a-zA-Z0-9\/:\.\-_\u4e00-\u9fa5]*$/;
  const isValid = pathReg.test(purePath);

  if (!isValid) {
    console.warn("H5路径格式非法（含不允许字符）：", purePath);
    return null;
  }

  // 第五步：最终处理（去除末尾多余的/，避免重复路径如/path// → /path）
  const normalizedPath = purePath.replace(/\/+$/, "") || "/";

  return normalizedPath;
};
/**
 * 解析复杂参数
 * @param {object} params - 原始参数
 * @returns {object} 处理后的参数
 */
const parseComplexParams = (params) => {
  const result = {};
  Object.entries(params).forEach(([key, value]) => {
    if (value === undefined || value === null) return;

    if (Array.isArray(value)) {
      value.forEach((item) => {
        const encodedItem = encodeURIComponent(item);
        if (result[key]) {
          result[key] = `${result[key]},${encodedItem}`;
        } else {
          result[key] = encodedItem;
        }
      });
    } else if (typeof value === "object") {
      result[key] = encodeURIComponent(JSON.stringify(value));
    }
    // 基础类型直接保留
    else {
      result[key] = value;
    }
  });
  return result;
};

/**
 * 构建编码后的查询参数串
 * @param {object} params - 处理后的参数
 * @returns {string} 编码后的查询串
 */
const buildQueryString = (params) => {
  return Object.entries(params)
    .filter(
      ([_, value]) => value !== undefined && value !== null && value !== ""
    )
    .map(
      ([key, value]) =>
        `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
    )
    .join("&");
};

/**
 * web-view 加载成功
 */
const onWebViewLoad = () => {
  isLoading.value = false; // 隐藏加载中
};

/**
 * web-view 加载失败
 * @param {object} err - 错误信息
 */
const onWebViewError = (err) => {
  isLoading.value = false;
  errorMsg.value = `页面加载失败：${err.detail.errMsg}`;
  uni.showToast({ title: errorMsg.value, icon: "none", duration: 2000 });
  console.error("WebView 加载错误：", err);
  setTimeout(() => uni.navigateBack(), 1500);
};

/**
 * 接收 H5 发送的消息
 * @param {object} e - 消息事件
 */
const onWebViewMessage = (e) => {
  const h5Msg = e.detail.data[0]; // H5 发送的消息格式为 { data: [消息体] }
  console.log("接收 H5 消息：", h5Msg);

  // 示例：H5 触发「返回小程序」
  if (h5Msg.type === "navigateBack") {
    uni.navigateBack({ delta: h5Msg.delta || 1 });
  }

  if (h5Msg.type === "refreshToken") {
    appStore.refreshToken().then((newToken) => {
      const webview = uni.createSelectorQuery().select("#any-id");
      webview
        .context((res) => {
          res.context.postMessage({
            data: { type: "newToken", token: newToken },
          });
        })
        .exec();
    });
  }
};
</script>

<style scoped>
.webview-wrapper {
  width: 100vw;
  height: 100vh;
  position: relative;
}

.loading-mask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 999;
}

.loading-txt {
  margin-top: 16rpx;
  font-size: 28rpx;
  color: #666;
}
</style>
