<template>
  <div class="terminal-container">
    <div class="terminal-header">
      <span>SSH终端</span>
      <div>
        <a-button @click="connect" type="primary" size="small">连接</a-button>
        <a-button @click="disconnect" size="small" style="margin-left: 8px">断开</a-button>
      </div>
    </div>

    <div class="terminal-body" ref="terminalBody">
      <div v-for="(line, index) in outputLines" :key="index" class="terminal-line">
        <span v-if="line.type === 'input'" class="input-prompt">$ </span>
        <span :class="line.type">{{ line.text }}</span>
      </div>
      <div class="terminal-input-line">
        <span class="input-prompt">$ </span>
        <input
          v-model="currentCommand"
          @keyup.enter="executeCommand"
          @keyup.up="historyUp"
          @keyup.down="historyDown"
          ref="commandInput"
          class="terminal-input"
        />
      </div>
    </div>

    <a-modal
      v-model:visible="connectionModalVisible"
      title="SSH连接配置"
      @ok="handleConnect"
      :ok-button-props="{ disabled: connecting }"
      :cancel-button-props="{ disabled: connecting }"
    >
      <a-form :model="connectionForm" :rules="formRules" layout="vertical">
        <a-form-item label="主机地址" name="host">
          <a-input v-model:value="connectionForm.host" />
        </a-form-item>
        <a-form-item label="端口" name="port">
          <a-input-number v-model:value="connectionForm.port" :min="1" :max="65535" />
        </a-form-item>
        <a-form-item label="用户名" name="username">
          <a-input v-model:value="connectionForm.username" />
        </a-form-item>
        <a-form-item label="密码" name="password">
          <a-input-password v-model:value="connectionForm.password" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, nextTick, onMounted, onBeforeUnmount } from 'vue'
import { message } from 'ant-design-vue'

interface TerminalLine {
  type: 'input' | 'output' | 'error' | 'system'
  text: string
}

interface ConnectionForm {
  host: string
  port: number
  username: string
  password: string
}

export default defineComponent({
  name: 'SshTerminal',
  setup() {
    const outputLines = ref<TerminalLine[]>([])
    const currentCommand = ref('')
    const commandHistory = ref<string[]>([])
    const historyIndex = ref(-1)
    const connectionModalVisible = ref(false)
    const connecting = ref(false)
    const connected = ref(false)
    const socket = ref<WebSocket | null>(null)
    const terminalBody = ref<HTMLElement | null>(null)
    const commandInput = ref<HTMLInputElement | null>(null)

    const connectionForm = ref<ConnectionForm>({
      host: '',
      port: 22,
      username: '',
      password: ''
    })

    const formRules = {
      host: [{ required: true, message: '请输入主机地址' }],
      port: [{ required: true, message: '请输入端口' }],
      username: [{ required: true, message: '请输入用户名' }],
      password: [{ required: true, message: '请输入密码' }]
    }

    const clientId = Math.random().toString(36).substring(2, 10)

    const addOutput = (type: TerminalLine['type'], text: string) => {
      outputLines.value.push({ type, text })
      scrollToBottom()
    }

    const scrollToBottom = () => {
      nextTick(() => {
        if (terminalBody.value) {
          terminalBody.value.scrollTop = terminalBody.value.scrollHeight
        }
      })
    }

    const connect = () => {
      connectionModalVisible.value = true
    }

    const handleConnect = () => {
      connecting.value = true
      initWebSocket()
    }

    const initWebSocket = () => {
      const wsUrl = `ws://${window.location.host}/jeecg-boot/ws/ssh/${clientId}`
      socket.value = new WebSocket(wsUrl)

      socket.value.onopen = () => {
        const { host, port, username, password } = connectionForm.value
        const connectMsg = `connect:${host}:${port}:${username}:${password}`
        socket.value?.send(connectMsg)
        connected.value = true
        connecting.value = false
        connectionModalVisible.value = false
        addOutput('system', 'SSH连接已建立')
      }

      socket.value.onmessage = (event) => {
        addOutput('output', event.data)
      }

      socket.value.onerror = (error) => {
        addOutput('error', '连接错误: ' + error)
        connecting.value = false
        connected.value = false
      }

      socket.value.onclose = () => {
        if (connected.value) {
          addOutput('system', 'SSH连接已断开')
        }
        connected.value = false
        connecting.value = false
      }
    }

    const disconnect = () => {
      if (connected.value && socket.value) {
        socket.value.send('disconnect')
        socket.value.close()
      }
    }

    const executeCommand = () => {
      if (!currentCommand.value.trim()) return

      if (!connected.value) {
        addOutput('system', '请先建立SSH连接')
        return
      }

      // 添加到历史记录
      commandHistory.value.push(currentCommand.value)
      historyIndex.value = commandHistory.value.length

      // 显示输入的命令
      addOutput('input', currentCommand.value)

      // 发送命令
      socket.value?.send(currentCommand.value)

      currentCommand.value = ''
      scrollToBottom()
    }

    const historyUp = () => {
      if (commandHistory.value.length === 0) return

      if (historyIndex.value > 0) {
        historyIndex.value--
        currentCommand.value = commandHistory.value[historyIndex.value]
      }
    }

    const historyDown = () => {
      if (historyIndex.value < commandHistory.value.length - 1) {
        historyIndex.value++
        currentCommand.value = commandHistory.value[historyIndex.value]
      } else if (historyIndex.value === commandHistory.value.length - 1) {
        historyIndex.value++
        currentCommand.value = ''
      }
    }

    const focusInput = () => {
      nextTick(() => {
        commandInput.value?.focus()
      })
    }

    onMounted(() => {
      focusInput()
    })

    onBeforeUnmount(() => {
      if (socket.value) {
        socket.value.close()
      }
    })

    return {
      outputLines,
      currentCommand,
      connectionModalVisible,
      connecting,
      connectionForm,
      formRules,
      terminalBody,
      commandInput,
      connect,
      handleConnect,
      disconnect,
      executeCommand,
      historyUp,
      historyDown
    }
  }
})
</script>

<style scoped>
.terminal-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #1e1e1e;
  color: #f0f0f0;
  border-radius: 4px;
  overflow: hidden;
}

.terminal-header {
  padding: 8px 16px;
  background-color: #333;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #444;
}

.terminal-body {
  flex: 1;
  padding: 8px;
  overflow-y: auto;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.terminal-line {
  margin-bottom: 4px;
  word-break: break-all;
  white-space: pre-wrap;
}

.terminal-input-line {
  display: flex;
  align-items: center;
}

.input-prompt {
  color: #4caf50;
  margin-right: 8px;
}

.terminal-input {
  flex: 1;
  background: transparent;
  border: none;
  color: #fff;
  font-family: 'Courier New', monospace;
  font-size: 14px;
  outline: none;
}

.output {
  color: #f0f0f0;
}

.error {
  color: #ff5252;
}

.input {
  color: #bbdefb;
}

.system {
  color: #ff9800;
}
</style>