<template>
  <view class="container">
    <!-- 连接配置区域 -->
    <view class="config-section">
      <view class="section-title">MQTT连接配置</view>
      <form @submit="handleConnect">
        <view class="form-item">
          <label>服务器地址：</label>
          <view class="input-wrapper">
            <input
                v-model="mqttConfig.broker"
                type="text"
                placeholder="如：ws://test.mosquitto.org:8080/mqtt"
                class="form-input"
            />
            <text class="clear-icon" @click="clearInput('broker')" v-if="mqttConfig.broker">×</text>
          </view>
        </view>
        <view class="form-item" v-if="false">
          <label>客户端ID：</label>
          <view class="input-wrapper">
            <input
                v-model="mqttConfig.clientId"
                type="text"
                placeholder="自动生成或自定义"
                class="form-input"
            />
            <text class="clear-icon" @click="clearInput('clientId')" v-if="mqttConfig.clientId">×</text>
          </view>
        </view>
        <view class="form-item">
          <label>用户名：</label>
          <view class="input-wrapper">
            <input
                v-model="mqttConfig.username"
                type="text"
                placeholder="可选"
                class="form-input"
            />
            <text class="clear-icon" @click="clearInput('username')" v-if="mqttConfig.username">×</text>
          </view>
        </view>
        <view class="form-item">
          <label>密码：</label>
          <view class="input-wrapper">
            <input
                v-model="mqttConfig.password"
                type="password"
                placeholder="可选"
                class="form-input"
            />
            <text class="clear-icon" @click="clearInput('password')" v-if="mqttConfig.password">×</text>
          </view>
        </view>
        <view class="form-item" v-if="false">
          <label>连接超时：</label>
          <view class="input-wrapper">
            <input
                v-model.number="mqttConfig.timeout"
                type="number"
                placeholder="默认30秒"
                class="form-input"
            />
            <text class="clear-icon" @click="clearInput('timeout')" v-if="mqttConfig.timeout">×</text>
          </view>
        </view>

        <view class="btn-group">
          <button
              type="primary"
              :disabled="isConnected"
              @click="handleConnect"
          >
            连接
          </button>
          <button
              type="warn"
              :disabled="!isConnected"
              @click="handleDisconnect"
          >
            断开连接
          </button>
        </view>
      </form>
    </view>

    <!-- 订阅区域 -->
    <view class="subscribe-section" v-if="isConnected">
      <view class="section-title">主题订阅</view>
      <view class="form-item">
        <label>订阅主题：</label>
        <view class="input-wrapper">
          <input
              v-model="subscribeTopic"
              type="text"
              placeholder="如：test/topic"
              class="form-input"
          />
          <text class="clear-icon" @click="subscribeTopic = ''" v-if="subscribeTopic">×</text>
        </view>
      </view>
      <button
          type="primary"
          @click="handleSubscribe"
      >
        订阅
      </button>

      <!-- 已订阅主题列表 -->
      <view class="topic-list" v-if="subscribedTopics.length">
        <view class="list-title">已订阅主题：</view>
        <view
            class="topic-item"
            v-for="(topic, index) in subscribedTopics"
            :key="index"
        >
          {{topic}}
          <button
              size="mini"
              type="warn"
              @click="handleUnsubscribe(topic)"
          >
            取消订阅
          </button>
        </view>
      </view>
    </view>


    <!-- 消息日志区域 -->
    <view class="log-section">
      <view class="section-title">消息日志</view>

      <!-- 日志过滤和清空区域 -->
      <view class="log-filter-wrapper">
        <!-- 主题过滤输入框 -->
        <view class="input-wrapper filter-input">
          <input
              v-model="logFilterKeyword"
              type="text"
              placeholder="输入主题关键词过滤日志（模糊匹配）"
              class="form-input"
          />
          <text class="clear-icon" @click="logFilterKeyword = ''" v-if="logFilterKeyword">×</text>
        </view>

        <!-- 清空日志按钮 -->
        <button
            size="mini"
            type="warn"
            @click="clearAllLogs"
            :disabled="messageLogs.length === 0"
            class="clear-log-btn"
        >
          清空日志
        </button>
      </view>

      <!-- 日志内容区域 -->
      <scroll-view
          class="log-content"
          scroll-y="true"
          :style="{height: logHeight + 'px'}"
      >
        <!-- 空日志提示 -->
        <view class="empty-log-tip" v-if="filteredLogs.length === 0">
          {{messageLogs.length === 0 ? '暂无消息日志' : '未找到匹配的日志内容'}}
        </view>

        <!-- 过滤后的日志列表 -->
        <view
            class="log-item"
            v-for="(log, index) in filteredLogs"
            :key="index"
            :class="{'received': log.type === 'received', 'sent': log.type === 'sent', 'system': log.type === 'system'}"
        >
          <view class="log-time">{{log.time}}</view>
          <view class="log-type">{{log.type === 'received' ? '接收' : log.type === 'sent' ? '发送' : '系统'}}</view>
          <!-- 主题区域 - 支持横向滚动 -->
          <view class="log-row">
            <text class="log-label">主题：</text>
            <view class="log-content-scroll">
              {{log.topic}}
            </view>
          </view>
          <!-- 消息内容区域 - 支持横向滚动 -->
          <view class="log-row">
            <text class="log-label">内容：</text>
            <view class="log-content-scroll">
              {{log.message}}
            </view>
          </view>
        </view>
      </scroll-view>
    </view>

    <!-- 发布消息区域 -->
    <view class="publish-section" v-if="isConnected">
      <view class="section-title">发布消息</view>
      <view class="form-item">
        <label>发布主题：</label>
        <view class="input-wrapper">
          <input
              v-model="publishTopic"
              type="text"
              placeholder="如：test/topic"
              class="form-input"
          />
          <text class="clear-icon" @click="publishTopic = ''" v-if="publishTopic">×</text>
        </view>
      </view>
      <view class="form-item">
        <label>消息内容：</label>
        <view class="textarea-wrapper">
          <textarea
              v-model="publishMessage"
              placeholder="输入要发布的消息内容"
              class="form-textarea"
          ></textarea>
          <text class="clear-icon textarea-clear" @click="publishMessage = ''" v-if="publishMessage">×</text>
        </view>
      </view>
      <button
          type="primary"
          @click="handlePublish"
      >
        发布消息
      </button>
    </view>
  </view>
</template>

<script>
import mqtt from 'mqtt/dist/mqtt'

export default {
  data() {
    return {
      // MQTT配置
      mqttConfig: {
        broker: 'wxs://mq.xiaoces.com:443/mqtt', // 公共测试服务器
        clientId: 'uniapp_mqtt_' + Math.random().toString(16).substr(2, 8),
        username: 'admin',
        password: 'Admin#12345678',
        timeout: 30
      },
      // 连接状态
      isConnected: false,
      client: null,
      // 订阅相关
      subscribeTopic: '',
      subscribedTopics: [],
      // 发布相关
      publishTopic: '',
      publishMessage: '',
      // 消息日志
      messageLogs: [],
      logHeight: 300, // 日志区域高度
      // 日志过滤
      logFilterKeyword: '' // 日志过滤关键词
    }
  },
  computed: {
    // 过滤后的日志列表
    filteredLogs() {
      if (!this.logFilterKeyword) {
        return this.messageLogs
      }
      // 模糊匹配主题（不区分大小写）
      const keyword = this.logFilterKeyword.toLowerCase()
      return this.messageLogs.filter(log => {
        return log.topic.toLowerCase().includes(keyword)
      })
    }
  },
  onReady() {
    // 计算日志区域高度
    uni.getSystemInfo({
      success: (res) => {
        this.logHeight = res.windowHeight - 650 // 调整高度适配过滤栏
      }
    })
  },
  onUnload() {
    // 页面卸载时断开连接
    if (this.client && this.isConnected) {
      console.info("mqtt链接已关闭")
      this.client.end()
    }
  },
  onHide() {
    // 页面卸载时断开连接
    if (this.client && this.isConnected) {
      console.info("mqtt链接已关闭")
      this.client.end()
    }
  },
  methods: {
    // 清除配置项输入框内容
    clearInput(field) {
      if (field === 'timeout') {
        this.mqttConfig[field] = ''
      } else {
        this.$set(this.mqttConfig, field, '')
      }
    },

    // 清空所有消息日志
    clearAllLogs() {
      uni.showModal({
        title: '确认清空',
        content: '是否确定清空所有消息日志？',
        success: (res) => {
          if (res.confirm) {
            this.messageLogs = []
            this.logFilterKeyword = '' // 清空过滤关键词
            uni.showToast({
              title: '日志已清空',
              icon: 'success',
              duration: 1500
            })
          }
        }
      })
    },

    // 添加日志
    addLog(type, topic, message) {
      const time = new Date().toLocaleTimeString()
      this.messageLogs.unshift({
        time,
        type, // received/sent/system
        topic,
        message
      })
      // 限制日志数量
      if (this.messageLogs.length > 100) {
        this.messageLogs.pop()
      }
    },

    // 连接MQTT服务器
    handleConnect() {
      if (!this.mqttConfig.broker) {
        uni.showToast({
          title: '请输入服务器地址',
          icon: 'none'
        })
        return
      }

      try {
        // 配置连接选项
        const options = {
          clientId: this.mqttConfig.clientId || 'uniapp_mqtt_' + Math.random().toString(16).substr(2, 8),
          username: this.mqttConfig.username,
          password: this.mqttConfig.password,
          connectTimeout: (this.mqttConfig.timeout || 30) * 1000,
          keepalive: 60,
          clean: true,
          reconnectPeriod: 0
        }

        // 创建客户端并连接
        this.client = mqtt.connect(this.mqttConfig.broker, options)

        // 连接成功回调
        this.client.on('connect', () => {
          this.isConnected = true
          this.addLog('system', '', 'MQTT连接成功')
          uni.showToast({
            title: '连接成功',
            icon: 'success'
          })
        })

        // 接收消息回调
        this.client.on('message', (topic, message) => {
          this.addLog('received', topic, message.toString())
        })

        // 连接断开回调
        this.client.on('close', () => {
          this.isConnected = false
          this.subscribedTopics = []
          this.addLog('system', '', 'MQTT连接已断开')
        })

        // 错误回调
        this.client.on('error', (error) => {
          this.isConnected = false
          this.addLog('system', '', '连接错误：' + error.message)
          uni.showToast({
            title: '连接失败：' + error.message,
            icon: 'none',
            duration: 3000
          })
        })
      } catch (error) {
        this.addLog('system', '', '连接异常：' + error.message)
        uni.showToast({
          title: '连接异常：' + error.message,
          icon: 'none',
          duration: 3000
        })
      }
    },

    // 断开连接
    handleDisconnect() {
      if (this.client) {
        this.client.end()
        this.isConnected = false
        this.subscribedTopics = []
        this.addLog('system', '', '已手动断开MQTT连接')
        uni.showToast({
          title: '已断开连接',
          icon: 'success'
        })
      }
    },

    // 订阅主题
    handleSubscribe() {
      if (!this.subscribeTopic) {
        uni.showToast({
          title: '请输入订阅主题',
          icon: 'none'
        })
        return
      }

      if (this.subscribedTopics.includes(this.subscribeTopic)) {
        uni.showToast({
          title: '该主题已订阅',
          icon: 'none'
        })
        return
      }

      this.client.subscribe(this.subscribeTopic, (error) => {
        if (error) {
          this.addLog('system', this.subscribeTopic, '订阅失败：' + error.message)
          uni.showToast({
            title: '订阅失败',
            icon: 'none'
          })
        } else {
          this.subscribedTopics.push(this.subscribeTopic)
          this.addLog('system', this.subscribeTopic, '订阅成功')
          uni.showToast({
            title: '订阅成功',
            icon: 'success'
          })
        }
      })
    },

    // 取消订阅
    handleUnsubscribe(topic) {
      this.client.unsubscribe(topic, (error) => {
        if (error) {
          this.addLog('system', topic, '取消订阅失败：' + error.message)
          uni.showToast({
            title: '取消订阅失败',
            icon: 'none'
          })
        } else {
          this.subscribedTopics = this.subscribedTopics.filter(item => item !== topic)
          this.addLog('system', topic, '取消订阅成功')
          uni.showToast({
            title: '取消订阅成功',
            icon: 'success'
          })
        }
      })
    },

    // 发布消息
    handlePublish() {
      if (!this.publishTopic) {
        uni.showToast({
          title: '请输入发布主题',
          icon: 'none'
        })
        return
      }

      if (!this.publishMessage) {
        uni.showToast({
          title: '请输入消息内容',
          icon: 'none'
        })
        return
      }

      this.client.publish(this.publishTopic, this.publishMessage, (error) => {
        if (error) {
          this.addLog('system', this.publishTopic, '发布失败：' + error.message)
          uni.showToast({
            title: '发布失败',
            icon: 'none'
          })
        } else {
          this.addLog('sent', this.publishTopic, this.publishMessage)
          uni.showToast({
            title: '发布成功',
            icon: 'success'
          })
          // 清空消息输入框
          this.publishMessage = ''
        }
      })
    }
  }
}
</script>

<style scoped>
.container {
  padding: 15px;
  background-color: #f5f5f5;
  min-height: 100vh;
}

.config-section, .subscribe-section, .publish-section, .log-section {
  background-color: #fff;
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 15px;
}

.section-title {
  font-size: 16px;
  font-weight: bold;
  color: #333;
  border-bottom: 1px solid #eee;
  padding-bottom: 8px;
  margin-bottom: 15px;
}

/* 日志过滤和清空区域 */
.log-filter-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 15px;
}

/* 过滤输入框 */
.filter-input {
  flex: 1;
}

/* 清空日志按钮 */
.clear-log-btn {
  height: 40px;
  line-height: 40px;
  padding: 0 15px;
  white-space: nowrap;
}

.form-item {
  display: flex;
  flex-direction: column;
  margin-bottom: 12px;
}

.form-item label {
  font-size: 14px;
  color: #666;
  margin-bottom: 5px;
}

/* 输入框容器 - 包含清除按钮 */
.input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.form-input {
  flex: 1;
  height: 40px;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 0 30px 0 10px; /* 右侧留出清除按钮空间 */
  font-size: 14px;
  /* 开启横向滚动 */
  white-space: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch; /* 顺滑滚动 */
}

/* 文本域容器 */
.textarea-wrapper {
  position: relative;
}

.form-textarea {
  width: 100%;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 10px 30px 10px 10px; /* 右侧留出清除按钮空间 */
  font-size: 14px;
  min-height: 100px;
  box-sizing: border-box;
}

/* 清除按钮样式 */
.clear-icon {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  line-height: 20px;
  text-align: center;
  font-size: 18px;
  color: #999;
  cursor: pointer;
  z-index: 10;
}

/* 文本域清除按钮位置调整 */
.textarea-clear {
  top: 10px;
  transform: none;
}

.clear-icon:hover {
  color: #f00;
}

.btn-group {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}

.btn-group button {
  flex: 1;
}

.topic-list {
  margin-top: 15px;
}

.list-title {
  font-size: 14px;
  color: #666;
  margin-bottom: 8px;
}

.topic-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 10px;
  background-color: #f9f9f9;
  border-radius: 4px;
  margin-bottom: 5px;
}

.log-section {
  margin-top: 15px;
}

.log-content {
  background-color: #f9f9f9;
  border-radius: 4px;
  padding: 10px;
}

/* 空日志提示 */
.empty-log-tip {
  text-align: center;
  color: #999;
  padding: 20px 0;
  font-size: 14px;
}

.log-item {
  padding: 8px;
  border-bottom: 1px solid #eee;
  margin-bottom: 5px;
  font-size: 14px;
  border-radius: 4px;
}

.log-item.received {
  background-color: #e8f5e9;
}

.log-item.sent {
  background-color: #e3f2fd;
}

.log-item.system {
  background-color: #fff8e1;
}

.log-time {
  color: #999;
  font-size: 12px;
  margin-bottom: 3px;
}

.log-type {
  font-weight: bold;
  margin-bottom: 3px;
}

/* 日志行容器 - 标签+滚动内容 */
.log-row {
  display: flex;
  align-items: flex-start;
  margin-bottom: 3px;
  width: 100%;
}

/* 日志标签（主题：/内容：） */
.log-label {
  color: #666;
  flex-shrink: 0; /* 标签不收缩 */
  margin-right: 5px;
}

/* 日志内容滚动容器 */
.log-content-scroll {
  flex: 1;
  white-space: nowrap; /* 不换行 */
  overflow-x: auto; /* 横向滚动 */
  -webkit-overflow-scrolling: touch; /* 移动端顺滑滚动 */
  padding-bottom: 2px;
  color: #333;
  /* 隐藏滚动条但保留滚动功能 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE/Edge */
}

/* 隐藏Chrome等浏览器的滚动条 */
.log-content-scroll::-webkit-scrollbar {
  display: none;
}

/* 修复之前的样式冲突 */
.log-topic, .log-message {
  display: none;
}
</style>