<template>
  <view class="aigc-recharge-page">
    <TopNavBar
      title="积分充值"
      title-align="left"
      background="transparent"
      title-color="#172033"
      back-icon-color="#172033"
      :align-with-menu-button="true"
      :z-index="3"
      @back="handleBack"
    />

    <view class="aigc-recharge-content">
      <BalanceCard
        :points="balancePoints"
        @ledger="handleOpenLedger"
      />

      <RechargePackageList
        :packages="rechargeOptions"
        :selected-key="selectedRechargeKey"
        @select="handleSelectRechargeOption"
      />

      <CustomAmountCard
        v-model="customAmount"
        :selected="rechargeMode === 'custom'"
        @select="handleSelectCustomAmount"
      />

      <RechargeFooter
        :price="payPrice"
        :loading="paying"
        :agreed="agreementAccepted"
        :agreement-ready="agreementReady"
        @update:agreed="agreementAccepted = $event"
        @view-agreement="handleViewAgreement"
        @pay="handlePay"
      />
    </view>

    <AgreePopup
      :visible="agreementVisible"
      title="积分充值协议"
      :agreement="agreementContent"
      @close="agreementVisible = false"
    />
  </view>
</template>

<script setup>
import { computed, ref } from "vue";
import { onHide, onLoad, onShow, onUnload } from "@dcloudio/uni-app";
import TopNavBar from "@/components/TopNavBar/index.vue";
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
import AgreePopup from "@/pages/login/components/AgreePopup/index.vue";
import { getPointsTopUpAgreement } from "@/request/api/AigcApi.js";
import {
  confirmVirtualRechargeOrder,
  createVirtualRechargeOrder,
  getVirtualRechargeOptions,
  getVirtualRechargeOrder,
} from "@/request/api/VirtualRechargeApi.js";
import BalanceCard from "./components/BalanceCard/index.vue";
import CustomAmountCard from "./components/CustomAmountCard/index.vue";
import RechargeFooter from "./components/RechargeFooter/index.vue";
import RechargePackageList from "./components/RechargePackageList/index.vue";
import {
  getPendingVirtualRechargeOrderNo,
  removePendingVirtualRechargeOrderNo,
  setPendingVirtualRechargeOrderNo,
} from "./services/pendingVirtualRecharge.js";
import {
  getWechatClientPlatform,
  getWechatLoginCode,
  requestWechatVirtualPayment,
} from "./services/wechatVirtualPayment.js";
import {
  buildVirtualRechargeOrderPayload,
  classifyVirtualRechargeStatus,
  normalizeVirtualPaymentOrder,
  VIRTUAL_RECHARGE_STATUS_KIND,
} from "./utils/virtualRecharge.js";

const ORDER_QUERY_INTERVAL = 2000;
const MAX_ORDER_QUERY_ATTEMPTS = 5;

const { pointBalance: balancePoints, fetchCurrentCredit } = useCurrentCredit();
const rechargeOptions = ref([]);
const selectedRechargeOption = ref(null);
const customAmount = ref("");
const rechargeMode = ref("package");
const paying = ref(false);
const reconciling = ref(false);
const agreementAccepted = ref(false);
const agreementContent = ref("");
const agreementLoading = ref(false);
const agreementVisible = ref(false);

let orderQueryTimer = null;
let orderQueryResolver = null;
let pageVisible = false;

const agreementReady = computed(() => Boolean(agreementContent.value.trim()));

const selectedRechargeKey = computed(() => {
  if (rechargeMode.value !== "package") return "";
  return String(selectedRechargeOption.value?.optionCode || "");
});

const payPrice = computed(() => {
  if (rechargeMode.value === "custom") {
    const amount = Number(customAmount.value);
    return Number.isInteger(amount) ? amount : 0;
  }

  const amountFen = Number(selectedRechargeOption.value?.expectedAmountFen);
  return Number.isInteger(amountFen) && amountFen > 0 ? amountFen / 100 : 0;
});

const showToast = (title, icon = "none") => {
  uni.showToast({ title, icon });
};

const clearOrderQueryTimer = () => {
  if (orderQueryTimer) {
    clearTimeout(orderQueryTimer);
    orderQueryTimer = null;
  }
  if (orderQueryResolver) {
    orderQueryResolver(false);
    orderQueryResolver = null;
  }
};

const waitForNextOrderQuery = () => {
  if (!pageVisible) return Promise.resolve(false);

  return new Promise((resolve) => {
    orderQueryResolver = resolve;
    orderQueryTimer = setTimeout(() => {
      orderQueryTimer = null;
      orderQueryResolver = null;
      resolve(pageVisible);
    }, ORDER_QUERY_INTERVAL);
  });
};

const fetchRechargeOptions = async () => {
  try {
    const res = await getVirtualRechargeOptions();
    if (res?.code === 0 && Array.isArray(res.data)) {
      rechargeOptions.value = res.data;
      if (rechargeMode.value === "package") {
        selectedRechargeOption.value = res.data[0] || null;
      }
      return;
    }

    rechargeOptions.value = [];
    selectedRechargeOption.value = null;
  } catch (error) {
    console.error("获取虚拟支付充值档位失败", error);
    rechargeOptions.value = [];
    selectedRechargeOption.value = null;
  }
};

const fetchPointsTopUpAgreement = async (showError = false) => {
  if (agreementLoading.value) return false;

  agreementLoading.value = true;
  try {
    const res = await getPointsTopUpAgreement();
    const content = typeof res?.data === "string" ? res.data.trim() : "";
    if (res?.code === 0 && content) {
      agreementContent.value = content;
      return true;
    }

    agreementContent.value = "";
    agreementAccepted.value = false;
    if (showError) showToast(res?.msg || "协议加载失败，请重试");
  } catch (error) {
    console.error("获取积分充值协议失败", error);
    agreementContent.value = "";
    agreementAccepted.value = false;
    if (showError) showToast("协议加载失败，请重试");
  } finally {
    agreementLoading.value = false;
  }

  return false;
};

const finishOrderByStatus = async (orderData) => {
  const statusKind = classifyVirtualRechargeStatus(orderData?.status);

  if (statusKind === VIRTUAL_RECHARGE_STATUS_KIND.PAID) {
    removePendingVirtualRechargeOrderNo();
    await fetchCurrentCredit();
    showToast("充值成功", "success");
    return true;
  }

  if (statusKind === VIRTUAL_RECHARGE_STATUS_KIND.REFUNDED) {
    removePendingVirtualRechargeOrderNo();
    await fetchCurrentCredit();
    showToast("充值订单已退款");
    return true;
  }

  if (statusKind === VIRTUAL_RECHARGE_STATUS_KIND.FAILED) {
    removePendingVirtualRechargeOrderNo();
    showToast("充值订单异常，请重新发起支付");
    return true;
  }

  return false;
};

const getPaymentErrorMessage = (error) => {
  switch (Number(error?.errCode)) {
    case -2:
      return "已取消支付";
    case -4:
      return "支付被微信风控拦截";
    case -15007:
      return "微信登录状态已过期，请重新发起支付";
    default:
      return "支付失败，请重试";
  }
};

const reconcileVirtualRechargeOrder = async (
  rechargeOrderNo,
  { clientPaymentError = null, showPendingToast = true } = {}
) => {
  if (reconciling.value || !rechargeOrderNo) return "skipped";

  reconciling.value = true;
  let latestOrder = null;

  try {
    let confirmArgs = {};
    try {
      const wxLoginCode = await getWechatLoginCode();
      confirmArgs = { wxLoginCode };
    } catch (error) {
      console.warn("刷新微信登录凭证失败，将使用现有服务端会话确认订单", error);
    }

    try {
      const confirmRes = await confirmVirtualRechargeOrder(
        rechargeOrderNo,
        confirmArgs
      );
      if (confirmRes?.code === 0 && confirmRes.data) {
        latestOrder = confirmRes.data;
        if (await finishOrderByStatus(latestOrder)) return "terminal";
      }
    } catch (error) {
      console.error("服务端确认虚拟支付订单失败", error);
    }

    if (Number(clientPaymentError?.errCode) === -2 && latestOrder?.status === "UNPAID") {
      removePendingVirtualRechargeOrderNo();
      showToast("已取消支付");
      return "cancelled";
    }

    for (let attempt = 0; attempt < MAX_ORDER_QUERY_ATTEMPTS; attempt += 1) {
      const shouldContinue = await waitForNextOrderQuery();
      if (!shouldContinue) return "paused";

      try {
        const queryRes = await getVirtualRechargeOrder(rechargeOrderNo);
        if (queryRes?.code === 0 && queryRes.data) {
          latestOrder = queryRes.data;
          if (await finishOrderByStatus(latestOrder)) return "terminal";
        }
      } catch (error) {
        console.error("查询虚拟支付充值订单失败", error);
      }
    }

    if (clientPaymentError && latestOrder?.status === "UNPAID") {
      removePendingVirtualRechargeOrderNo();
      showToast(getPaymentErrorMessage(clientPaymentError));
      return "client-failed";
    }

    if (showPendingToast) {
      showToast("支付结果确认中，请稍后返回查看");
    }
    return "pending";
  } finally {
    reconciling.value = false;
  }
};

const recoverPendingVirtualRechargeOrder = async () => {
  const rechargeOrderNo = getPendingVirtualRechargeOrderNo();
  if (!rechargeOrderNo || paying.value || reconciling.value) return;

  paying.value = true;
  uni.showLoading({ title: "正在确认支付结果...", mask: true });
  try {
    await reconcileVirtualRechargeOrder(rechargeOrderNo);
  } finally {
    uni.hideLoading();
    paying.value = false;
  }
};

const handleBack = () => {
  const pages = getCurrentPages();
  if (pages.length > 1) uni.navigateBack();
};

const handleOpenLedger = () => {
  uni.navigateTo({
    url: "/pages-aigc/pointsDetails/pointsDetails",
    fail: () => showToast("积分明细"),
  });
};

const handleSelectRechargeOption = (option) => {
  rechargeMode.value = "package";
  selectedRechargeOption.value = option;
  customAmount.value = "";
};

const handleSelectCustomAmount = () => {
  rechargeMode.value = "custom";
  selectedRechargeOption.value = null;
};

const handleViewAgreement = async () => {
  if (agreementReady.value) {
    agreementVisible.value = true;
    return;
  }

  if (agreementLoading.value) {
    showToast("协议加载中，请稍候");
    return;
  }

  const loaded = await fetchPointsTopUpAgreement(true);
  if (loaded) agreementVisible.value = true;
};

const validateRechargeSelection = () => {
  if (rechargeMode.value === "package") {
    if (!String(selectedRechargeOption.value?.optionCode || "").trim()) {
      throw new Error("请选择充值档位");
    }
    return;
  }

  const amountText = String(customAmount.value || "").trim();
  const amount = Number(amountText);
  if (!/^\d{1,6}$/.test(amountText) || amount < 1 || amount > 999999) {
    throw new Error("请输入1至999999的整数充值金额");
  }
};

const handlePay = async () => {
  if (paying.value) return;

  try {
    validateRechargeSelection();
  } catch (error) {
    showToast(error.message);
    return;
  }

  if (agreementLoading.value) {
    showToast("协议加载中，请稍候");
    return;
  }
  if (!agreementReady.value) {
    showToast("协议加载失败，请重试");
    return;
  }
  if (!agreementAccepted.value) {
    showToast("请先阅读并同意积分充值协议");
    return;
  }

  paying.value = true;
  clearOrderQueryTimer();
  uni.showLoading({ title: "正在发起支付...", mask: true });

  try {
    const clientPlatform = getWechatClientPlatform();
    const wxLoginCode = await getWechatLoginCode();
    const createOrderPayload = buildVirtualRechargeOrderPayload({
      mode: rechargeMode.value,
      rechargeOptionCode: selectedRechargeOption.value?.optionCode,
      rechargeAmount: customAmount.value,
      wxLoginCode,
      clientPlatform,
    });
    const createRes = await createVirtualRechargeOrder(createOrderPayload);

    if (createRes?.code !== 0 || !createRes.data) {
      throw new Error(createRes?.msg || "充值下单失败，请重试");
    }

    const paymentOrder = normalizeVirtualPaymentOrder(createRes.data);
    setPendingVirtualRechargeOrderNo(paymentOrder.rechargeOrderNo);
    uni.hideLoading();

    let clientPaymentError = null;
    try {
      await requestWechatVirtualPayment(paymentOrder);
    } catch (error) {
      clientPaymentError = error;
    }

    pageVisible = true;
    uni.showLoading({ title: "正在确认支付结果...", mask: true });
    await reconcileVirtualRechargeOrder(paymentOrder.rechargeOrderNo, {
      clientPaymentError,
    });
  } catch (error) {
    console.error("虚拟支付积分充值失败", error);
    showToast(error?.message || "充值下单失败，请重试");
  } finally {
    uni.hideLoading();
    paying.value = false;
  }
};

onLoad(() => {
  agreementAccepted.value = false;
  fetchRechargeOptions();
  fetchPointsTopUpAgreement();
});

onShow(() => {
  pageVisible = true;
  fetchCurrentCredit();
  recoverPendingVirtualRechargeOrder();
});

onHide(() => {
  pageVisible = false;
  clearOrderQueryTimer();
});

onUnload(() => {
  pageVisible = false;
  clearOrderQueryTimer();
});
</script>

<style scoped lang="scss">
@import "./styles/index.scss";
</style>
