<template>
  <view class="container">
    <image
      class="bg"
      src="../static/charge-ordering-bg.svg"
      mode="widthFix"
    />
    <view class="body">
      <view class="iphonex-placeholder"></view>
      <view
        class="status flex-center transition"
        :style="{
          opacity: step >= 1 ? '1' : '0',
        }"
      >
        <image
          :class="['border', `${step <= 2 ? 'border-animation' : ''}`]"
          src="../static/charge-ordering-border.png"
          @load="onImgLoad"
        />
        <view class="timer flex-column flex-center">
          <block v-if="step === 1">
            <view>
              <text class="fw-600" style="font-size: 100rpx">{{
                status.time
              }}</text>
              <text class="fs-40 fw-500 ml-10">s</text>
            </view>
            <view class="fs-26">充电启动中</view>
          </block>
          <block v-else-if="step === 2">
            <image
              class="icon"
              src="../static/charge-ordering-icon.png"
            />
            <view class="fs-26 mt-10">充电中...</view>
          </block>
          <block v-else-if="step === 3">
            <image
              class="icon"
              src="../static/charge-ordering-finish.png"
            />
            <view class="fs-26 mt-10">充电结束</view>
          </block>
        </view>
      </view>
    </view>
  </view>

  <!-- 停止充电倒计时遮罩 -->
  <view class="stop-countdown-mask" v-if="stoppingStatus.isStopping">
    <view class="stop-countdown-modal">
      <view class="stop-countdown-title">正在停止充电</view>
      <view class="stop-countdown-time">
        <text class="stop-countdown-number">{{ stoppingStatus.countdown }}</text>
        <text class="stop-countdown-unit">秒</text>
      </view>
      <view class="stop-countdown-tip">请等待充电桩响应...</view>
    </view>
  </view>

  <style-bottom-view>
    <view
      class="transition pl-60 pr-60 pb-40"
      :style="{
        opacity: step >= 1 ? '1' : '0',
      }"
    >
      <view class="mb-40" v-if="step === 2 || step === 3">
        <shadow-card :list="chargeInfo"></shadow-card>
      </view>
      <style-button
        v-if="step === 1 || step === 2"
        type="warning"
        size="small"
        @click="cancel"
        >停止充电</style-button
      >
      <style-button
        v-if="step === 3"
        type="primary"
        size="small"
        @click="reLaunch"
        >返回首页</style-button
      >
    </view>
  </style-bottom-view>
</template>

<script setup lang="ts">
import { onHide, onLoad, onShow } from "@dcloudio/uni-app";
import { cancelCharge, fetchChargeStatus, startCharge } from "../../api/charge";
import { ref } from "vue";
import { format } from "../utils/date";
import { to, reLaunch } from "@/utils/navigate";
import { requireAuth } from "@/utils/auth";

let timer: any;
let statusTimer: any;
let stopCountdownTimer: any;
const step = ref(0);
const options = ref<any>();
const status = ref({
  time: 30,
  start: false,
  cancel: false,
  error: false,
});
const chargeInfo = ref<any[]>([]);
// 停止充电状态
const stoppingStatus = ref({
  isStopping: false,
  countdown: 15,
});
const startStartTimer = () => {
  if (status.value.start || status.value.cancel || status.value.error) {
    timer && clearTimeout(timer);
    return;
  }
  timer = setTimeout(() => {
    if (status.value.time <= 1 && !status.value.start) {
      uni.showModal({
        title: "充电错误",
        content: "出现问题，请重试",
        showCancel: false,
        confirmText: "知道了",
        confirmColor: "#2d9e95",
        success() {
          uni.navigateBack();
        },
      });
      return;
    }
    status.value.time = status.value.time - 1;
    startStartTimer();
  }, 1000);
};
const startStatusTimer = () => {
  statusTimer = setTimeout(() => {
    if (status.value.cancel) {
      return;
    }
    fetchChargeStatus()
      .then((res) => {
        if (status.value.cancel) {
          return;
        }
        if (res && res.isStarted) {
          setChargeData(res);
        }
        startStatusTimer();
      })
      .catch(() => {
        startStatusTimer();
      });
  }, 30000);
};
const start = () => {
  step.value = 1;
  startStartTimer();
  startCharge(options.value && options.value.connectorId ? options.value.connectorId : "")
    .then(() => {
      fetchStatus();
    })
    .catch((err) => {
      setTimeout(() => {
        status.value.error = true;
        timer && clearTimeout(timer);
        uni.showModal({
          content: `${err.errMsg}`,
          showCancel: false,
          success: () => {
            uni.navigateBack();
          },
        });
      }, 300);
    });
};

const cancel = () => {
  uni.showModal({
    title: "停止充电",
    content: "是否停止充电",
    cancelText: "停止",
    cancelColor: "#999999",
    confirmText: "点错了",
    confirmColor: "#2d9e95",
    success: (res) => {
      if (res.cancel) {
        clearTimeout(timer);
        clearTimeout(statusTimer);
        status.value.cancel = true;
        if ([1, 2].includes(step.value)) {
          if (status.value.start) {
            finish();
          } else {
            // 显示停止充电倒计时遮罩
            stoppingStatus.value.isStopping = true;
            stoppingStatus.value.countdown = 15;
            startStopCountdown();
            cancelCharge(
              options.value && options.value.connectorId ? options.value.connectorId : ""
            )
              .then(() => {
                // 停止充电后，轮询等待充电桩真正停止
                waitForChargeStopped();
              })
              .catch(() => {
                clearStopCountdown();
                uni.showToast({
                  title: "停止充电失败，请重试",
                  icon: "none",
                });
              });
          }
        }
      }
    },
  });
};

/**
 * 开始停止充电倒计时
 */
const startStopCountdown = () => {
  stopCountdownTimer = setInterval(() => {
    if (stoppingStatus.value.countdown > 1) {
      stoppingStatus.value.countdown--;
    }
  }, 1000);
};

/**
 * 清除停止充电倒计时
 */
const clearStopCountdown = () => {
  stoppingStatus.value.isStopping = false;
  if (stopCountdownTimer) {
    clearInterval(stopCountdownTimer);
    stopCountdownTimer = null;
  }
};

/**
 * 轮询等待充电桩真正停止
 * 最多等待15秒，每2秒检查一次充电状态
 */
const waitForChargeStopped = () => {
  const maxRetry = 8; // 最多重试8次，每2秒检查一次，约15秒
  let retryCount = 0;
  
  const checkStopped = () => {
    fetchChargeStatus()
      .then((res) => {
        // 充电状态：0：预约中 1：启动中 2：充电中 3：停止中 4：已结束 5：未知
        // 如果状态为 4（已结束）或 5（未知）或没有返回数据，认为已停止
        if (!res || [4, 5].includes(res.chargeStatus)) {
          clearStopCountdown();
          // 设置手工停止充电标识
          getApp<any>().globalData.manualStop = true;
          uni.showToast({
            title: "已停止充电",
            icon: "success",
          });
          setTimeout(() => {
            uni.navigateBack();
          }, 1500);
          return;
        }
        
        // 如果状态为 3（停止中），继续等待
        if (res.chargeStatus === 3) {
          retryCount++;
          if (retryCount >= maxRetry) {
            clearStopCountdown();
            // 设置手工停止充电标识
            getApp<any>().globalData.manualStop = true;
            uni.showModal({
              title: "温馨提示",
              content: "充电桩响应较慢，已发送停止指令，请稍后确认充电状态",
              showCancel: false,
              confirmText: "知道了",
              success: () => {
                uni.navigateBack();
              },
            });
            return;
          }
          // 继续轮询
          setTimeout(checkStopped, 2000);
          return;
        }
        
        // 如果状态仍为 1 或 2（充电中/启动中），继续等待
        if ([1, 2].includes(res.chargeStatus)) {
          retryCount++;
          if (retryCount >= maxRetry) {
            clearStopCountdown();
            // 设置手工停止充电标识
            getApp<any>().globalData.manualStop = true;
            uni.showModal({
              title: "温馨提示",
              content: "充电桩响应较慢，已发送停止指令，请稍后确认充电状态",
              showCancel: false,
              confirmText: "知道了",
              success: () => {
                uni.navigateBack();
              },
            });
            return;
          }
          // 继续轮询
          setTimeout(checkStopped, 2000);
          return;
        }
        
        // 其他状态，认为已停止
        clearStopCountdown();
        getApp<any>().globalData.manualStop = true;
        uni.showToast({
          title: "已停止充电",
          icon: "success",
        });
        setTimeout(() => {
          uni.navigateBack();
        }, 1500);
      })
      .catch(() => {
        retryCount++;
        if (retryCount >= maxRetry) {
          clearStopCountdown();
          getApp<any>().globalData.manualStop = true;
          uni.showToast({
            title: "已停止充电",
            icon: "none",
          });
          setTimeout(() => {
            uni.navigateBack();
          }, 1500);
          return;
        }
        // 出错后继续轮询
        setTimeout(checkStopped, 2000);
      });
  };
  
  checkStopped();
};
const finish = () => {
  // 显示停止充电倒计时遮罩
  stoppingStatus.value.isStopping = true;
  stoppingStatus.value.countdown = 15;
  startStopCountdown();
  fetchChargeStatus()
    .then((res) => {
      if (res.isStarted) {
        // 当前充电中
        const start = res.startTime
          ? new Date(res.startTime.replace(/-/g, "/"))
          : new Date();
        const end = new Date();
        const diff = parseInt(`${(end.getTime() - start.getTime()) / 1000}`);
        const min = parseInt(`${diff / 60}`);
        const time =
          min >= 60
            ? `${parseInt(`${min / 60}`)}小时${parseInt(
                `${min - parseInt(`${min / 60}`) * 60}`
              )}分钟`
            : `${parseInt(`${diff / 60}`)}分钟`;
        const endFormat = format("y-M-d h:m:s");
        const totalMoney = (res.totalMoney / 100).toFixed(2);
        const _chargeInfo = [
          {
            label: "累计充电量",
            value: `${res.totalPower}度`,
          },
          {
            label: "累计费用",
            value: `${totalMoney}元`,
          },
          {
            label: "开始时间",
            value: res.startTime || format("y-M-d h:m:s"),
          },
          {
            label: "结束时间",
            value: endFormat,
          },
          {
            label: "累计用时",
            value: time,
          },
          {
            label: "订单号",
            value: res.startChargeSeq,
            copy:true
          }
        ];
        if (res.soc) {
          _chargeInfo.unshift({
            label: "剩余电量",
            value: `${res.soc}%`,
          });
        }
        chargeInfo.value = _chargeInfo;
        cancelCharge(options.value && options.value.connectorId ? options.value.connectorId : "")
          .then(() => {
            if (res.failReason) {
              clearStopCountdown();
              uni.showModal({
                content: res.failReason,
                showCancel: false,
                success() {
                  uni.navigateBack();
                },
              });
              return;
            }
            // 停止充电后，轮询等待充电桩真正停止
            waitForChargeStoppedAndShowResult();
          })
          .catch((err) => {
            console.log(err);
            clearStopCountdown();
            uni.showToast({
              title: "停止充电失败，请重试",
              icon: "none",
            });
          });
      }
    })
    .catch((err) => {
      console.log(err);
      clearStopCountdown();
      uni.showModal({
        title: "温馨提示",
        content: "出现错误，请重试",
        showCancel: false,
        confirmText: "重试",
        confirmColor: "#2d9e95",
        success: () => {
          finish();
        },
      });
    });
};

/**
 * 轮询等待充电桩真正停止，然后显示充电结束界面
 * 用于 finish 函数调用
 */
const waitForChargeStoppedAndShowResult = () => {
  const maxRetry = 8; // 最多重试8次，每2秒检查一次，约15秒
  let retryCount = 0;
  
  const checkStopped = () => {
    fetchChargeStatus()
      .then((res) => {
        // 充电状态：0：预约中 1：启动中 2：充电中 3：停止中 4：已结束 5：未知
        // 如果状态为 4（已结束）或 5（未知）或没有返回数据，认为已停止
        if (!res || [4, 5].includes(res.chargeStatus)) {
          clearStopCountdown();
          // 设置手工停止充电标识
          getApp<any>().globalData.manualStop = true;
          // 显示充电结束界面
          step.value = 3;
          return;
        }
        
        // 如果状态为 3（停止中），继续等待
        if (res.chargeStatus === 3) {
          retryCount++;
          if (retryCount >= maxRetry) {
            clearStopCountdown();
            // 设置手工停止充电标识
            getApp<any>().globalData.manualStop = true;
            // 超时也显示结束界面
            step.value = 3;
            return;
          }
          // 继续轮询
          setTimeout(checkStopped, 2000);
          return;
        }
        
        // 如果状态仍为 1 或 2（充电中/启动中），继续等待
        if ([1, 2].includes(res.chargeStatus)) {
          retryCount++;
          if (retryCount >= maxRetry) {
            clearStopCountdown();
            // 设置手工停止充电标识
            getApp<any>().globalData.manualStop = true;
            // 超时也显示结束界面
            step.value = 3;
            return;
          }
          // 继续轮询
          setTimeout(checkStopped, 2000);
          return;
        }
        
        // 其他状态，认为已停止
        clearStopCountdown();
        getApp<any>().globalData.manualStop = true;
        step.value = 3;
      })
      .catch(() => {
        retryCount++;
        if (retryCount >= maxRetry) {
          clearStopCountdown();
          getApp<any>().globalData.manualStop = true;
          step.value = 3;
          return;
        }
        // 出错后继续轮询
        setTimeout(checkStopped, 2000);
      });
  };
  
  checkStopped();
};
const setChargeData = (res: any) => {
  const start = res.startTime
          ? new Date(res.startTime.replace(/-/g, "/"))
          : new Date();
  const end = new Date();
  const diff = parseInt(`${(end.getTime() - start.getTime()) / 1000}`);
  const min = parseInt(`${diff / 60}`);
  const time =
    min >= 60
      ? `${parseInt(`${min / 60}`)}小时${parseInt(
          `${min - parseInt(`${min / 60}`) * 60}`
        )}分钟`
      : `${parseInt(`${diff / 60}`)}分钟`;
  const totalMoney = (res.totalMoney / 100).toFixed(2);
  const _chargeInfo = [
    {
      label: "累计充电量",
      value: `${res.totalPower}度`,
    },
    {
      label: "累计费用",
      value: `${totalMoney}元`,
    },
    {
      label: "开始时间",
      value: res.startTime || format("y-M-d h:m:s"),
    },
    {
      label: "累计用时",
      value: time,
    },
  ];
  if (res.soc) {
    _chargeInfo.unshift({
      label: "剩余电量",
      value: `${res.soc}%`,
    });
  }
  chargeInfo.value = _chargeInfo;
};
const fetchStatus = (data?: any) => {
  if (status.value.cancel) {
    return;
  }
  const promise = data ? Promise.resolve(data) : fetchChargeStatus();
  promise
    .then((res) => {
      if (res.isStarted) {
        // 当前充电中
        status.value.start = true;
        step.value = 2;
        setChargeData(res);
        startStatusTimer();
      }
    })
    .catch((err) => {
      console.log(err);
      setTimeout(() => {
        fetchStatus(data);
      }, 1000);
    });
};
const onImgLoad = () => {
  fetchChargeStatus()
    .then((res) => {
      if (res && res.isAppointment) {
        to(`/pages-charge/appointment/appointment?connectorId=${options.value.connectorId}`);
        return;
      }
      if (res && res.isStarted) {
        // 已有充电中的订单，直接进入充电中页面
        if (options.value && options.value.connectorId !== res.connectorId) {
          // 同步为当前充电订单的充电桩，保证停止充电等操作正确
          options.value = { ...options.value, connectorId: res.connectorId };
        }
        fetchStatus(res);
      } else {
        reLaunch();
      }
    })
    .catch((err) => {
      console.log(err);
      uni.showModal({
        title: "温馨提示",
        content: "查询充电状态异常，请返回重试",
        showCancel: false,
        confirmText: "知道了",
        confirmColor: "#2d9e95",
        success: () => {
          reLaunch();
        },
      });
    });
};

onLoad((_options: any) => {
  if (!requireAuth()) {
    return;
  }
  options.value = _options;
});
onHide(() => {
  timer && clearTimeout(timer);
  statusTimer && clearTimeout(statusTimer);
});
onShow(() => {
  startStartTimer();
});
</script>

<style lang="scss">
.container {
  height: 100vh;
  width: 100%;
  background-color: #fff;
  position: relative;
  overflow: hidden;

  .bg {
    width: 100%;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    transform-origin: center;
  }

  .body {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 100%;

    .iphonex-placeholder {
      box-sizing: content-box;
      padding-bottom: constant(safe-area-inset-bottom);
      padding-bottom: env(safe-area-inset-bottom);
    }

    .status {
      width: 420rpx;
      height: 420rpx;
      border-radius: 50%;
      position: relative;
      margin: 0 auto;
      margin-top: 130rpx;

      .border {
        width: 100%;
        height: 100%;
      }

      .border-animation {
        animation: rot 3s linear infinite;
      }

      .timer {
        position: absolute;
        width: 340rpx;
        height: 340rpx;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        background: linear-gradient(180deg, #ffffff 0%, #ecf3ff 100%);
        box-shadow: 0px 18rpx 30rpx rgba(0, 0, 0, 0.1);
        border-radius: 50%;
        .icon {
          width: 152rpx;
          height: 152rpx;
        }
      }
    }
  }
}

@keyframes rot {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

// 停止充电倒计时遮罩样式
.stop-countdown-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.6);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}

.stop-countdown-modal {
  width: 400rpx;
  background-color: #fff;
  border-radius: 24rpx;
  padding: 60rpx 40rpx;
  text-align: center;
}

.stop-countdown-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 30rpx;
}

.stop-countdown-time {
  display: flex;
  align-items: baseline;
  justify-content: center;
  margin-bottom: 20rpx;
}

.stop-countdown-number {
  font-size: 80rpx;
  font-weight: 600;
  color: #2d9e95;
}

.stop-countdown-unit {
  font-size: 28rpx;
  color: #666;
  margin-left: 8rpx;
}

.stop-countdown-tip {
  font-size: 24rpx;
  color: #999;
}
</style>
