<template>
  <view class="page">
    <base-background />
    <custom-navbar title="NFC配对" />

    <view class="content">
      <view class="status-card">
        <view class="status-header">
          <view :class="['status-dot', socketConnected ? 'online' : 'offline']" />
          <text class="status-title">{{ connectionText }}</text>
        </view>
        <text class="status-desc">
          请保持手机在线，等待刷卡设备将NFC卡号传递到本页面。
        </text>
        <view class="card-box" :class="{ ready: !!cardNo }">
          <text class="card-label">NFC卡号</text>
          <text class="card-value">{{ cardNo || "等待刷卡..." }}</text>
        </view>
        <view v-if="connectionError" class="error-text">{{ connectionError }}</view>
        <view v-else-if="lastMessage" class="hint-text">{{ lastMessage }}</view>
        <view class="status-actions">
          <view class="text-btn" @click="handleRetry">重新连接</view>
          <view class="text-btn" @click="resetCard" v-if="cardNo">清空卡号</view>
        </view>
      </view>

      <view class="form-card">
        <view class="field">
          <text class="label">设备 MAC 地址</text>
          <input
            v-model.trim="deviceMac"
            class="input"
            maxlength="32"
            placeholder="请输入设备 MAC"
            placeholder-class="placeholder"
          />
        </view>
        <view class="field">
          <text class="label">NFC 卡号</text>
          <input
            v-model="cardNo"
            class="input"
            disabled
            placeholder="等待刷卡"
            placeholder-class="placeholder"
          />
        </view>

        <view v-if="unitId" class="field readonly">
          <text class="label">绑定单元 ID</text>
          <text class="unit-value">{{ unitId }}</text>
        </view>

        <view
          :class="['primary-btn', { disabled: !canSubmit || binding }]"
          @click="handleBind"
        >
          {{ binding ? "提交中..." : "提交绑定" }}
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import BaseBackground from "@/components/base-background/base-background.vue";
import CustomNavbar from "@/components/custom-navbar/custom-navbar.vue";
import { getRequestConfig } from "@/utils/request.js";
import { bindNfcCard } from "@/api/memorial/index.js";

const NFC_WS_PATH = "/ws/nfc/swipeCard";

export default {
  components: {
    BaseBackground,
    CustomNavbar,
  },
  data() {
    return {
      unitId: "",
      socketTask: null,
      socketConnected: false,
      deviceMac: "",
      cardNo: "",
      binding: false,
      connectionError: "",
      lastMessage: "",
      usingGlobalSocketEvents: false,
      globalSocketHandlers: null,
    };
  },
  computed: {
    canSubmit() {
      return !!this.deviceMac && !!this.cardNo;
    },
    connectionText() {
      if (this.connectionError) {
        return "连接异常";
      }
      return this.socketConnected ? "已连接，等待刷卡" : "连接中...";
    },
  },
  onLoad(options = {}) {
    if (options.unitId) {
      this.unitId = options.unitId;
    }
    if (options.mac) {
      this.deviceMac = options.mac;
    }
    this.initSocket();
  },
  onUnload() {
    this.cleanupSocket();
  },
  methods: {
    buildSocketUrl() {
      try {
        const { baseUrl } = getRequestConfig();
        if (!baseUrl) return "";
        const protocol = baseUrl.startsWith("https") ? "wss" : "ws";
        const host = baseUrl.replace(/^https?:\/\//, "").replace(/\/$/, "");
        const query = this.unitId ? `?unitId=${this.unitId}` : "";
        return `${protocol}://${host}${NFC_WS_PATH}${query}`;
      } catch (error) {
        console.error("构建WebSocket地址失败", error);
        return "";
      }
    },
    initSocket() {
      this.connectionError = "";
      this.lastMessage = "";
      const url = this.buildSocketUrl();
      if (!url) {
        this.connectionError = "缺少WebSocket地址，请检查配置";
        return;
      }
      this.cleanupSocket();
      console.log("NFC配对页面发起WebSocket连接:", url);
      this.socketTask = uni.connectSocket({ url });
      if (!this.socketTask) {
        this.connectionError = "当前环境不支持WebSocket";
        return;
      }
      if (typeof this.socketTask.onOpen === "function") {
        this.bindTaskSocketEvents();
      } else {
        this.bindGlobalSocketEvents();
      }
    },
    cleanupSocket() {
      if (this.socketTask && typeof this.socketTask.close === "function") {
        try {
          this.socketTask.close();
        } catch (error) {
          console.warn("关闭WebSocket失败", error);
        }
      } else {
        uni.closeSocket && uni.closeSocket({});
      }
      this.unbindGlobalSocketEvents();
      this.socketTask = null;
      this.socketConnected = false;
    },
    bindTaskSocketEvents() {
      if (!this.socketTask) return;
      this.socketTask.onOpen(() => {
        console.log("NFC WebSocket 已连接");
        this.socketConnected = true;
        this.connectionError = "";
      });
      this.socketTask.onClose((event) => {
        console.warn("NFC WebSocket 连接关闭", event);
        this.socketConnected = false;
        this.socketTask = null;
      });
      this.socketTask.onError((error) => {
        console.error("NFC WebSocket 错误", error);
        this.connectionError = "连接失败，请重试";
        this.socketConnected = false;
      });
      this.socketTask.onMessage((event) => {
        this.handleSocketMessage(event);
      });
    },
    bindGlobalSocketEvents() {
      if (this.usingGlobalSocketEvents) return;
      this.usingGlobalSocketEvents = true;
      this.globalSocketHandlers = {
        open: () => {
          console.log("NFC WebSocket 已连接 (global handler)");
          this.socketConnected = true;
          this.connectionError = "";
        },
        close: (event) => {
          console.warn("NFC WebSocket 连接关闭", event);
          this.socketConnected = false;
        },
        error: (error) => {
          console.error("NFC WebSocket 错误", error);
          this.connectionError = "连接失败，请重试";
          this.socketConnected = false;
        },
        message: (event) => {
          this.handleSocketMessage(event);
        },
      };
      uni.onSocketOpen && uni.onSocketOpen(this.globalSocketHandlers.open);
      uni.onSocketClose && uni.onSocketClose(this.globalSocketHandlers.close);
      uni.onSocketError && uni.onSocketError(this.globalSocketHandlers.error);
      uni.onSocketMessage &&
        uni.onSocketMessage(this.globalSocketHandlers.message);
    },
    unbindGlobalSocketEvents() {
      if (!this.usingGlobalSocketEvents || !this.globalSocketHandlers) return;
      const { open, close, error, message } = this.globalSocketHandlers;
      uni.offSocketOpen && open && uni.offSocketOpen(open);
      uni.offSocketClose && close && uni.offSocketClose(close);
      uni.offSocketError && error && uni.offSocketError(error);
      uni.offSocketMessage && message && uni.offSocketMessage(message);
      this.usingGlobalSocketEvents = false;
      this.globalSocketHandlers = null;
    },
    handleSocketMessage(event) {
      let message = event?.data;
      this.lastMessage = "";
      try {
        if (typeof message === "string") {
          const trimmed = message.trim();
          if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
            const parsed = JSON.parse(trimmed);
            if (parsed.cardNo || parsed.cardNumber || parsed.nfcNo) {
              this.cardNo = parsed.cardNo || parsed.cardNumber || parsed.nfcNo;
              this.lastMessage = "已接收卡号";
              uni.showToast({ title: "收到卡号", icon: "success" });
              return;
            }
            this.lastMessage = parsed.msg || trimmed;
            return;
          } else {
            this.cardNo = trimmed;
            this.lastMessage = "已接收卡号";
            uni.showToast({ title: "收到卡号", icon: "success" });
            return;
          }
        } else if (typeof message === "object" && message) {
          const data = message.data || message;
          if (data.cardNo || data.cardNumber || data.nfcNo) {
            this.cardNo = data.cardNo || data.cardNumber || data.nfcNo;
            this.lastMessage = "已接收卡号";
            uni.showToast({ title: "收到卡号", icon: "success" });
            return;
          }
        }
        this.lastMessage = "收到未知消息";
      } catch (error) {
        console.error("解析WebSocket消息失败", error, message);
        this.lastMessage = "消息解析失败";
      }
    },
    resetCard() {
      this.cardNo = "";
      this.lastMessage = "";
    },
    handleRetry() {
      this.initSocket();
    },
    async handleBind() {
      if (!this.canSubmit || this.binding) return;
      this.binding = true;
      uni.showLoading({ title: "提交中...", mask: true });
      try {
        const payload = {
          memorialMac: this.deviceMac,
          nfcMac: this.cardNo,
        };
        if (this.unitId) {
          payload.unitId = this.unitId;
        }
        const res = await bindNfcCard(payload);
        if (res && (res.code === 200 || res.status === 200)) {
          uni.showToast({ title: res.msg || "绑定成功", icon: "success" });
          setTimeout(() => {
            uni.navigateBack({ delta: 1 });
          }, 800);
        } else {
          uni.showToast({
            title: (res && res.msg) || "绑定失败",
            icon: "none",
          });
        }
      } catch (error) {
        console.error("提交绑定失败", error);
        uni.showToast({ title: "提交失败，请重试", icon: "none" });
      } finally {
        this.binding = false;
        uni.hideLoading();
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.page {
  min-height: 100vh;
  width: 100%;
  padding-bottom: 40rpx;
  box-sizing: border-box;
}

.content {
  padding: 0 32rpx 60rpx;
  box-sizing: border-box;
}

.status-card,
.form-card {
  background: rgba(255, 255, 255, 0.92);
  border-radius: 24rpx;
  padding: 32rpx;
  margin-top: 32rpx;
  box-shadow: 0 12rpx 32rpx rgba(0, 0, 0, 0.06);
}

.status-header {
  display: flex;
  align-items: center;
  gap: 16rpx;
}

.status-dot {
  width: 16rpx;
  height: 16rpx;
  border-radius: 50%;
  background: #f0b400;
}

.status-dot.online {
  background: #3ac569;
}

.status-dot.offline {
  background: #f56c6c;
}

.status-title {
  font-size: 30rpx;
  font-weight: 600;
  color: #333;
}

.status-desc {
  margin-top: 12rpx;
  font-size: 24rpx;
  color: #999;
  line-height: 1.5;
}

.card-box {
  margin-top: 24rpx;
  border: 2rpx dashed #f0b400;
  border-radius: 20rpx;
  padding: 24rpx;
  background: #fff9eb;
}

.card-box.ready {
  border-color: #3ac569;
  background: #effbf4;
}

.card-label {
  font-size: 24rpx;
  color: #666;
}

.card-value {
  display: block;
  margin-top: 16rpx;
  font-size: 36rpx;
  font-weight: 600;
  color: #333;
  word-break: break-all;
}

.error-text {
  margin-top: 16rpx;
  color: #f56c6c;
  font-size: 24rpx;
}

.hint-text {
  margin-top: 16rpx;
  color: #999;
  font-size: 24rpx;
}

.status-actions {
  margin-top: 24rpx;
  display: flex;
  gap: 32rpx;
}

.text-btn {
  font-size: 26rpx;
  color: #4a90e2;
}

.field {
  margin-bottom: 32rpx;
}

.field.readonly {
  padding: 24rpx;
  background: #f9f9f9;
  border-radius: 16rpx;
}

.label {
  font-size: 26rpx;
  color: #666;
  margin-bottom: 12rpx;
  display: block;
}

.input {
  width: 100%;
  height: 88rpx;
  border-radius: 16rpx;
  background: #f8f8f8;
  padding: 0 24rpx;
  font-size: 28rpx;
  color: #333;
  box-sizing: border-box;
}

.placeholder {
  color: #bbb;
}

.unit-value {
  font-size: 30rpx;
  color: #333;
  word-break: break-all;
}

.primary-btn {
  height: 96rpx;
  border-radius: 16rpx;
  background: linear-gradient(135deg, #f0b400, #f08400);
  color: #fff;
  font-size: 30rpx;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 12rpx;
}

.primary-btn.disabled {
  opacity: 0.5;
}
</style>

