<template>
  <div class="page-container">
    <!-- 搜索表单 -->
    <div class="search-form">
      <el-form :model="searchForm" inline>
        <el-form-item>
          <el-input v-model.trim="searchForm.streamSn" placeholder="stream sn" clearable @keyup.enter="handleSearch" />
        </el-form-item>
        <el-form-item>
          <el-input v-model.trim="searchForm.name" placeholder="name" clearable @keyup.enter="handleSearch" />
        </el-form-item>
        <el-form-item>
          <el-select v-model="searchForm.lssId" placeholder="LSS" clearable filterable style="width: 180px">
            <el-option v-for="lss in lssOptions" :key="lss.lssId" :label="lss.lssId" :value="lss.lssId" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-input v-model.trim="searchForm.cameraId" placeholder="设备ID" clearable @keyup.enter="handleSearch" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :icon="Search" @click="handleSearch">{{ t('查询') }}</el-button>
          <el-button :icon="RefreshRight" @click="handleReset">{{ t('重置') }}</el-button>
          <el-button type="primary" :icon="Plus" @click="handleAdd">{{ t('新增') }}</el-button>
        </el-form-item>
      </el-form>
    </div>

    <!-- 数据表格 -->
    <div class="table-wrapper">
      <el-table
        ref="tableRef"
        v-loading="loading"
        :data="streamList"
        stripe
        size="default"
        height="100%"
        @sort-change="handleSortChange"
      >
        <el-table-column prop="streamSn" :label="t('stream sn')" width="220" show-overflow-tooltip>
          <template #default="{ row }">
            <el-link type="primary" @click="handleEdit(row)">{{ row.streamSn }}</el-link>
          </template>
        </el-table-column>
        <el-table-column prop="name" :label="t('名称')" show-overflow-tooltip>
          <template #default="{ row }">
            <span>{{ row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="lssId" :label="t('LSS')" width="160" show-overflow-tooltip>
          <template #default="{ row }">
            <span>{{ row.lssId || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="cameraId" :label="t('设备ID')" show-overflow-tooltip>
          <template #default="{ row }">
            <span>{{ row.cameraId || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="pushMethod" :label="t('推流方式')" align="center">
          <template #default="{ row }">
            <el-tag size="small">{{ row.pushMethod || 'ffmpeg' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="commandTemplate" :label="t('命令模板')" align="center">
          <template #default="{ row }">
            <el-link type="primary" @click="openCommandDialog(row)">{{ t('查看') }}</el-link>
          </template>
        </el-table-column>
        <el-table-column :label="t('推流控制')" align="center">
          <template #default="{ row }">
            {{ row.status === '1' ? t('开启') : t('关闭') }}
            <el-switch
              :model-value="row.status === '1'"
              :loading="row._starting || row._stopping"
              inline-prompt
              @change="(val: boolean) => handleToggleStream(row, val)"
            />
          </template>
        </el-table-column>
        <el-table-column prop="startedAt" :label="t('启动时间')" width="160" align="center">
          <template #default="{ row }">
            {{ formatDateTime(row.startedAt) }}
          </template>
        </el-table-column>
        <el-table-column prop="stoppedAt" :label="t('关闭时间')" width="160" align="center">
          <template #default="{ row }">
            {{ formatDateTime(row.stoppedAt) }}
          </template>
        </el-table-column>
        <el-table-column :label="t('操作')" align="center" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" link @click="handleEdit(row)">
              <Icon icon="mdi:note-edit-outline" width="20" height="20" />
            </el-button>
            <el-button type="primary" link @click="handleViewCloudflare(row)">
              <Icon icon="mdi:play-circle-outline" width="20" height="20" />
            </el-button>
            <el-button type="danger" link @click="handleDelete(row)">
              <Icon icon="mdi:delete" width="20" height="20" />
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

    <!-- 新增/编辑抽屉 -->
    <el-drawer
      v-model="drawerVisible"
      direction="rtl"
      size="550px"
      :with-header="false"
      destroy-on-close
      class="stream-drawer"
    >
      <div class="drawer-content">
        <div class="drawer-header">{{ drawerTitle }}</div>
        <div class="drawer-body">
          <el-form ref="formRef" :model="form" :rules="rules" label-width="auto" class="stream-form">
            <el-form-item label="名称:" prop="name">
              <el-input v-model="form.name" placeholder="例如: 测试推流-001" style="width: 300px" />
            </el-form-item>
            <el-form-item label="LSS 节点:" prop="lssId">
              <el-select v-model="form.lssId" placeholder="请选择 LSS 节点" clearable filterable style="width: 300px">
                <el-option
                  v-for="lss in lssOptions"
                  :key="lss.lssId"
                  :label="`${lss.lssId} - ${lss.lssName}`"
                  :value="lss.lssId"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="摄像头:" prop="cameraId">
              <el-select v-model="form.cameraId" placeholder="请选择摄像头" clearable filterable style="width: 300px">
                <el-option
                  v-for="camera in cameraOptions"
                  :key="camera.cameraId"
                  :label="`${camera.cameraId} - ${camera.cameraName}`"
                  :value="camera.cameraId"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="推流方式:" prop="pushMethod">
              <el-select disabled v-model="form.pushMethod" placeholder="请选择" style="width: 300px">
                <el-option label="ffmpeg" value="ffmpeg" />
              </el-select>
            </el-form-item>
            <!-- <el-form-item label="超时时间:" prop="timeoutSeconds">
              <el-input-number v-model="form.timeoutSeconds" :min="1" :max="300" placeholder="秒" style="width: 150px" />
              <span style="margin-left: 8px; color: #909399">秒</span>
            </el-form-item> -->
            <el-form-item label="命令模板:" prop="commandTemplate">
              <div class="code-editor-wrapper">
                <CodeEditor
                  v-model="form.commandTemplate"
                  language="bash"
                  height="200px"
                  placeholder="#!/bin/bash&#10;# FFmpeg 命令模板，可使用 {RTSP_URL} 等变量"
                />
              </div>
            </el-form-item>
          </el-form>
        </div>
        <div class="drawer-footer">
          <el-button @click="drawerVisible = false">{{ t('取消') }}</el-button>
          <el-button type="primary" :loading="submitLoading" @click="handleSubmit">
            {{ isEdit ? t('更新') : t('添加') }}
          </el-button>
        </div>
      </div>
    </el-drawer>

    <!-- 命令模板查看/编辑弹窗 -->
    <el-dialog v-model="commandDialogVisible" :title="t('命令模板')" width="800px" destroy-on-close>
      <CodeEditor
        v-model="currentCommandTemplate"
        language="bash"
        height="450px"
        placeholder="#!/bin/bash&#10;# FFmpeg 推流命令模板"
      />
      <template #footer>
        <el-button @click="commandDialogVisible = false">{{ t('关闭') }}</el-button>
        <el-button type="primary" :loading="commandUpdateLoading" @click="handleUpdateCommandTemplate">
          {{ t('更新') }}
        </el-button>
      </template>
    </el-dialog>

    <!-- 流媒体播放抽屉 -->
    <el-drawer
      v-model="mediaDrawerVisible"
      direction="rtl"
      size="90%"
      :with-header="false"
      destroy-on-close
      class="media-drawer"
    >
      <!-- 左上角关闭按钮 -->
      <div class="drawer-close-btn" @click="mediaDrawerVisible = false">
        <el-icon :size="20">
          <Close />
        </el-icon>
      </div>
      <div class="media-drawer-content">
        <!-- 左侧：视频播放区域 -->
        <div class="video-area">
          <div class="video-header">
            <div class="header-left">
              <span class="title">{{ currentMediaStream?.name || t('流媒体播放') }}</span>
              <el-tag v-if="playbackInfo.isLive" type="success" size="small">{{ t('直播中') }}</el-tag>
              <el-tag v-else type="info" size="small">{{ t('离线') }}</el-tag>
            </div>
            <el-button type="danger" size="small" @click="mediaDrawerVisible = false">
              <Icon icon="mdi:close" width="16" height="16" />
              {{ t('关闭') }}
            </el-button>
          </div>
          <div class="player-container">
            <div v-if="!playbackInfo.videoId" class="player-placeholder">
              <el-icon :size="80" color="#666">
                <VideoPlay />
              </el-icon>
              <p>{{ t('暂无视频流') }}</p>
            </div>
            <VideoPlayer
              v-else
              ref="playerRef"
              player-type="cloudflare"
              :video-id="playbackInfo.videoId"
              :customer-domain="playbackInfo.customerDomain"
              :use-iframe="true"
              :autoplay="playConfig.autoplay"
              :muted="playConfig.muted"
              :controls="true"
            />
          </div>
          <!-- 底部播放控制 -->
          <div class="player-controls">
            <el-button type="primary" size="small" @click="handlePlay">{{ t('播放') }}</el-button>
            <el-button size="small" @click="handlePause">{{ t('暂停') }}</el-button>
            <el-button type="danger" size="small" @click="handlePlayerStop">{{ t('停止') }}</el-button>
            <el-button size="small" @click="handleScreenshot">{{ t('截图') }}</el-button>
            <el-button size="small" @click="handleFullscreen">{{ t('全屏') }}</el-button>
            <el-switch
              v-model="playConfig.muted"
              :active-text="t('静音')"
              :inactive-text="t('有声')"
              style="margin-left: 16px"
            />
          </div>
        </div>

        <!-- 右侧：PTZ 控制面板 -->
        <div class="control-panel">
          <!-- PTZ 方向控制 -->
          <div class="panel-section">
            <div class="section-title">{{ t('PTZ') }}</div>
            <div class="ptz-grid">
              <div
                class="ptz-btn"
                @mousedown="handlePTZ('UP_LEFT')"
                @mouseup="handlePTZStop"
                @mouseleave="handlePTZStop"
              >
                <el-icon>
                  <TopLeft />
                </el-icon>
              </div>
              <div class="ptz-btn" @mousedown="handlePTZ('UP')" @mouseup="handlePTZStop" @mouseleave="handlePTZStop">
                <el-icon>
                  <Top />
                </el-icon>
              </div>
              <div
                class="ptz-btn"
                @mousedown="handlePTZ('UP_RIGHT')"
                @mouseup="handlePTZStop"
                @mouseleave="handlePTZStop"
              >
                <el-icon>
                  <TopRight />
                </el-icon>
              </div>
              <div class="ptz-btn" @mousedown="handlePTZ('LEFT')" @mouseup="handlePTZStop" @mouseleave="handlePTZStop">
                <el-icon>
                  <Back />
                </el-icon>
              </div>
              <div class="ptz-btn ptz-center" @click="handlePTZStop">
                <el-icon>
                  <Refresh />
                </el-icon>
              </div>
              <div class="ptz-btn" @mousedown="handlePTZ('RIGHT')" @mouseup="handlePTZStop" @mouseleave="handlePTZStop">
                <el-icon>
                  <Right />
                </el-icon>
              </div>
              <div
                class="ptz-btn"
                @mousedown="handlePTZ('DOWN_LEFT')"
                @mouseup="handlePTZStop"
                @mouseleave="handlePTZStop"
              >
                <el-icon>
                  <BottomLeft />
                </el-icon>
              </div>
              <div class="ptz-btn" @mousedown="handlePTZ('DOWN')" @mouseup="handlePTZStop" @mouseleave="handlePTZStop">
                <el-icon>
                  <Bottom />
                </el-icon>
              </div>
              <div
                class="ptz-btn"
                @mousedown="handlePTZ('DOWN_RIGHT')"
                @mouseup="handlePTZStop"
                @mouseleave="handlePTZStop"
              >
                <el-icon>
                  <BottomRight />
                </el-icon>
              </div>
            </div>

            <!-- 缩放按钮 -->
            <div class="zoom-buttons">
              <el-button size="small" @mousedown="handleZoomIn" @mouseup="handlePTZStop" @mouseleave="handlePTZStop">
                <el-icon>
                  <ZoomIn />
                </el-icon>
              </el-button>
              <el-button size="small" @mousedown="handleZoomOut" @mouseup="handlePTZStop" @mouseleave="handlePTZStop">
                <el-icon>
                  <ZoomOut />
                </el-icon>
              </el-button>
            </div>

            <!-- 速度滑块 -->
            <div class="speed-slider">
              <span class="label">{{ t('速度') }}</span>
              <el-slider v-model="ptzSpeed" :min="10" :max="100" :step="10" size="small" />
              <span class="value">{{ ptzSpeed }}</span>
            </div>
          </div>

          <!-- 预置位列表 -->
          <div class="panel-section preset-section">
            <div class="section-title">
              <span>{{ t('预置位') }}</span>
              <el-button type="primary" link size="small" @click="loadPresets" :loading="presetsLoading">
                <el-icon>
                  <Refresh />
                </el-icon>
              </el-button>
            </div>
            <div class="preset-list" v-loading="presetsLoading">
              <div
                v-for="preset in presetList"
                :key="preset.token"
                :class="['preset-item', { active: activePresetToken === preset.token }]"
                @click="handleGotoPreset(preset)"
              >
                <span class="preset-index">{{ preset.token }}</span>
                <span class="preset-name">{{ preset.name || `Preset ${preset.token}` }}</span>
              </div>
              <el-empty
                v-if="!presetsLoading && presetList.length === 0"
                :description="t('暂无预置位')"
                :image-size="60"
              />
            </div>
          </div>
        </div>
      </div>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import {
  Search,
  RefreshRight,
  Plus,
  VideoPlay,
  Top,
  Bottom,
  Back,
  Right,
  TopLeft,
  TopRight,
  BottomLeft,
  BottomRight,
  Refresh,
  ZoomIn,
  ZoomOut,
  Close
} from '@element-plus/icons-vue'
import { Icon } from '@iconify/vue'
import dayjs from 'dayjs'
import { useI18n } from 'vue-i18n'
import { listLiveStreams, addLiveStream, updateLiveStream, deleteLiveStream } from '@/api/live-stream'
import { listAllLssNodes } from '@/api/lss'
import { adminListCameras } from '@/api/camera'
import { startStreamTask, stopStreamTask, getStreamPlayback } from '@/api/stream-push'
import VideoPlayer from '@/components/VideoPlayer.vue'
import CodeEditor from '@/components/CodeEditor.vue'
import { ptzStart, ptzStop, getPresets, gotoPreset, type PresetInfo } from '@/api/camera'
import type { LiveStreamDTO, LiveStreamStatus, LssNodeDTO, CameraInfoDTO, StreamChannelDTO } from '@/types'

const { t } = useI18n({ useScope: 'global' })
const route = useRoute()
const router = useRouter()

// 格式化时间
function formatDateTime(dateStr: string | undefined): string {
  if (!dateStr) return '-'
  return dayjs(dateStr).format('YYYY-MM-DD HH:mm:ss')
}

const loading = ref(false)
const submitLoading = ref(false)
const streamList = ref<LiveStreamDTO[]>([])
const drawerVisible = ref(false)
const formRef = ref<FormInstance>()

// 命令模板弹窗
const commandDialogVisible = ref(false)
const currentCommandTemplate = ref('')
const currentStreamId = ref<number | null>(null)
const commandUpdateLoading = ref(false)

// 流媒体播放抽屉
const mediaDrawerVisible = ref(false)
const currentMediaStream = ref<LiveStreamDTO | null>(null)
const playerRef = ref<InstanceType<typeof VideoPlayer>>()
const playbackInfo = ref<{
  videoId: string
  customerDomain: string
  hlsUrl?: string
  whepUrl?: string
  isLive: boolean
}>({
  videoId: '',
  customerDomain: '',
  isLive: false
})
const playConfig = reactive({
  autoplay: true,
  muted: true
})
// PTZ 控制
const ptzSpeed = ref(50)
const zoomValue = ref(0)

// 预置位
const presetList = ref<PresetInfo[]>([])
const presetsLoading = ref(false)
const activePresetToken = ref<string | null>(null)

// 下拉选项
const lssOptions = ref<LssNodeDTO[]>([])
const cameraOptions = ref<CameraInfoDTO[]>([])
const channelOptions = ref<StreamChannelDTO[]>([])

// 排序状态
const sortState = reactive<{
  prop: string
  order: 'ascending' | 'descending' | null
}>({
  prop: '',
  order: null
})

// 搜索表单
const searchForm = reactive<{
  streamSn: string
  name: string
  lssId: string
  cameraId: string
}>({
  streamSn: '',
  name: '',
  lssId: '',
  cameraId: ''
})

// 分页相关
const currentPage = ref(1)
const pageSize = ref(20)
const total = ref(0)

// 表单数据
const form = reactive<{
  id?: number
  name: string
  lssId: string
  cameraId: string
  channelId?: number
  pushMethod: string
  commandTemplate: string
  timeoutSeconds: number
  remark: string
  enabled: boolean
}>({
  name: '',
  lssId: '',
  cameraId: '',
  channelId: undefined,
  pushMethod: 'ffmpeg',
  commandTemplate: '',
  timeoutSeconds: 30,
  remark: '',
  enabled: true
})

const isEdit = computed(() => !!form.id)
const drawerTitle = computed(() => (isEdit.value ? t('编辑 Live Stream') : t('新增 Live Stream')))

const rules: FormRules = {
  name: [{ required: true, message: t('请输入名称'), trigger: 'blur' }],
  lssId: [{ required: true, message: t('请选择 LSS 节点'), trigger: 'change' }]
}

async function getList() {
  loading.value = true
  try {
    const params: Record<string, any> = {
      page: currentPage.value,
      size: pageSize.value
    }
    if (searchForm.streamSn) {
      params.streamSn = searchForm.streamSn
    }
    if (searchForm.name) {
      params.name = searchForm.name
    }
    if (searchForm.lssId) {
      params.lssId = searchForm.lssId
    }
    if (searchForm.cameraId) {
      params.cameraId = searchForm.cameraId
    }
    if (sortState.prop && sortState.order) {
      params.sortBy = sortState.prop
      params.sortDir = sortState.order === 'ascending' ? 'ASC' : 'DESC'
    }

    const res = await listLiveStreams(params)
    if (res.success) {
      streamList.value = res.data.list
      total.value = res.data.total || 0
    }
  } finally {
    loading.value = false
  }
}

async function loadOptions() {
  try {
    // 获取 LSS 节点列表
    const lssRes = await listAllLssNodes()
    if (lssRes.success && lssRes.data) {
      lssOptions.value = lssRes.data || []
    }
  } catch (error) {
    console.error('加载选项失败', error)
  }
}

// 监听 LSS 节点变化，加载对应的摄像头列表
watch(
  () => form.lssId,
  async (newLssId) => {
    // 清空当前选中的摄像头
    form.cameraId = ''
    cameraOptions.value = []

    if (newLssId) {
      try {
        const res = await adminListCameras({ lssId: newLssId, size: 1000 })
        if (res.success && res.data) {
          cameraOptions.value = res.data.list || []
        }
      } catch (error) {
        console.error('加载摄像头列表失败', error)
      }
    }
  }
)

function handleSearch() {
  currentPage.value = 1
  getList()
}

function handleReset() {
  searchForm.streamSn = ''
  searchForm.name = ''
  searchForm.lssId = ''
  searchForm.cameraId = ''
  currentPage.value = 1
  sortState.prop = ''
  sortState.order = null
  getList()
}

function handleSortChange({ prop, order }: { prop: string; order: 'ascending' | 'descending' | null }) {
  sortState.prop = prop || ''
  sortState.order = order
  getList()
}

function handleAdd() {
  Object.assign(form, {
    id: undefined,
    name: '',
    lssId: '',
    cameraId: '',
    channelId: undefined,
    pushMethod: 'ffmpeg',
    commandTemplate: '',
    timeoutSeconds: 30,
    remark: '',
    enabled: true
  })
  drawerVisible.value = true
}

function handleEdit(row: LiveStreamDTO) {
  Object.assign(form, {
    id: row.id,
    name: row.name,
    lssId: row.lssId || '',
    cameraId: row.cameraId || '',
    channelId: row.channelId,
    pushMethod: row.pushMethod || 'ffmpeg',
    commandTemplate: row.commandTemplate || '',
    timeoutSeconds: row.timeoutSeconds || 30,
    remark: row.remark || '',
    enabled: row.enabled
  })
  drawerVisible.value = true
}

async function handleDelete(row: LiveStreamDTO) {
  // 检查 status 必须为 0（已停止）
  if (row.status !== '0') {
    ElMessage.warning(t('只能删除已停止的 Live Stream'))
    return
  }

  // // 检查 stoppedAt 必须超过 24 小时
  // if (row.stoppedAt) {
  //   const stoppedTime = dayjs(row.stoppedAt)
  //   const hoursDiff = dayjs().diff(stoppedTime, 'hour')
  //   if (hoursDiff < 24) {
  //     ElMessage.warning(t('停止时间未超过24小时，暂时无法删除'))
  //     return
  //   }
  // } else {
  //   // 没有 stoppedAt 时间，不允许删除
  //   ElMessage.warning(t('停止时间未超过24小时，暂时无法删除'))
  //   return
  // }

  try {
    await ElMessageBox.confirm(t('确定要删除该 Live Stream 吗？'), t('提示'), {
      type: 'warning',
      confirmButtonText: t('确定'),
      cancelButtonText: t('取消')
    })

    const res = await deleteLiveStream(row.id)
    if (res.success) {
      ElMessage.success(t('删除成功'))
      getList()
    } else {
      ElMessage.error(res.errMessage || t('删除失败'))
    }
  } catch {
    // 用户取消
  }
}

async function handleSubmit() {
  if (!formRef.value) return

  await formRef.value.validate(async (valid) => {
    if (valid) {
      submitLoading.value = true
      try {
        if (isEdit.value) {
          const res = await updateLiveStream({
            id: form.id!,
            name: form.name,
            lssId: form.lssId || undefined,
            cameraId: form.cameraId || undefined,
            channelId: form.channelId,
            pushMethod: form.pushMethod || undefined,
            commandTemplate: form.commandTemplate || undefined,
            timeoutSeconds: form.timeoutSeconds,
            remark: form.remark || undefined,
            enabled: form.enabled
          })
          if (res.success) {
            ElMessage.success(t('修改成功'))
            drawerVisible.value = false
            getList()
          } else {
            ElMessage.error(res.errMessage || t('修改失败'))
          }
        } else {
          const res = await addLiveStream({
            name: form.name,
            lssId: form.lssId,
            cameraId: form.cameraId,
            channelId: form.channelId,
            pushMethod: form.pushMethod,
            commandTemplate: form.commandTemplate,
            timeoutSeconds: form.timeoutSeconds,
            remark: form.remark
          })
          if (res.success) {
            ElMessage.success(t('新增成功'))
            drawerVisible.value = false
            // 清除 URL 上的 lssId 和 action 参数
            if (route.query.action || route.query.lssId) {
              const newQuery = { ...route.query }
              delete newQuery.lssId
              delete newQuery.action
              router.replace({ path: '/live-stream', query: newQuery })
            }
            getList()
          } else {
            ElMessage.error(res.errMessage || t('新增失败'))
          }
        }
      } finally {
        submitLoading.value = false
      }
    }
  })
}

// 打开命令模板弹窗
function openCommandDialog(row: LiveStreamDTO) {
  currentStreamId.value = row.id
  currentCommandTemplate.value = row.commandTemplate || ''
  commandDialogVisible.value = true
}

// 更新命令模板
async function handleUpdateCommandTemplate() {
  if (!currentStreamId.value) return

  commandUpdateLoading.value = true
  try {
    const res = await updateLiveStream({
      id: currentStreamId.value,
      commandTemplate: currentCommandTemplate.value
    })
    if (res.success) {
      ElMessage.success(t('更新成功'))
      commandDialogVisible.value = false
      getList()
    } else {
      ElMessage.error(res.errMessage || t('更新失败'))
    }
  } catch (error) {
    console.error('更新命令模板失败', error)
    ElMessage.error(t('更新失败'))
  } finally {
    commandUpdateLoading.value = false
  }
}

// 切换推流状态
async function handleToggleStream(row: LiveStreamDTO, val: boolean) {
  if (val) {
    await handleStartStream(row)
  } else {
    await handleStopStream(row)
  }
}

// 启动推流
async function handleStartStream(row: LiveStreamDTO) {
  if (!row.cameraId) {
    ElMessage.warning(t('请先配置摄像头'))
    return
  }

  row._starting = true
  try {
    const res = await startStreamTask({
      name: row.name,
      lssId: row.lssId,
      cameraId: row.cameraId
    })
    if (res.success) {
      ElMessage.success(t('推流任务已启动'))
      getList()
    } else {
      ElMessage.error(res.errMessage || t('启动失败'))
    }
  } catch (error) {
    console.error('启动推流失败', error)
    ElMessage.error(t('启动推流失败'))
  } finally {
    row._starting = false
  }
}

// 停止推流
async function handleStopStream(row: LiveStreamDTO) {
  try {
    await ElMessageBox.confirm(t('确定要停止该推流任务吗？'), t('提示'), {
      type: 'warning',
      confirmButtonText: t('确定'),
      cancelButtonText: t('取消')
    })

    row._stopping = true
    const res = await stopStreamTask({ taskId: row.taskStreamSn, lssId: row.lssId })
    if (res.success) {
      ElMessage.success(t('推流任务已停止'))
      getList()
    } else {
      ElMessage.error(res.errMessage || t('停止失败'))
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('停止推流失败', error)
      ElMessage.error(t('停止推流失败'))
    }
  } finally {
    row._stopping = false
  }
}

// 从 playbackUrl 解析 videoId 和 customerDomain
function parsePlaybackUrl(playbackUrl: string): { videoId: string; customerDomain: string } | null {
  try {
    const url = new URL(playbackUrl)
    const customerDomain = url.hostname
    // URL 格式: https://domain/{videoId}/webRTC/play 或 https://domain/{videoId}/iframe
    const pathParts = url.pathname.split('/').filter(Boolean)
    if (pathParts.length > 0) {
      return { videoId: pathParts[0], customerDomain }
    }
  } catch (e) {
    console.error('解析 playbackUrl 失败', e)
  }
  return null
}

// 查看流媒体
async function handleViewCloudflare(row: LiveStreamDTO) {
  currentMediaStream.value = row

  // 默认值
  let videoId = ''
  let customerDomain = 'customer-pj89kn2ke2tcuh19.cloudflarestream.com'

  // 优先从 playbackUrl 解析
  if (row.playbackUrl) {
    const parsed = parsePlaybackUrl(row.playbackUrl)
    if (parsed) {
      videoId = parsed.videoId
      customerDomain = parsed.customerDomain
    }
  }

  // 尝试获取播放信息
  if (row.streamSn) {
    try {
      const res = await getStreamPlayback(row.streamSn)
      if (res.success && res.data) {
        playbackInfo.value = {
          videoId: videoId || row.streamSn,
          customerDomain,
          hlsUrl: res.data.hlsUrl,
          whepUrl: res.data.whepUrl,
          isLive: res.data.isLive
        }
      } else {
        playbackInfo.value = {
          videoId: videoId || row.streamSn,
          customerDomain,
          isLive: false
        }
      }
    } catch (error) {
      console.error('获取播放信息失败', error)
      playbackInfo.value = {
        videoId: videoId || row.streamSn,
        customerDomain,
        isLive: false
      }
    }
  } else if (videoId) {
    playbackInfo.value = {
      videoId,
      customerDomain,
      isLive: false
    }
  }

  mediaDrawerVisible.value = true
}

// 播放控制
function handlePlay() {
  playerRef.value?.play()
}

function handlePause() {
  playerRef.value?.pause()
}

function handlePlayerStop() {
  playerRef.value?.stop()
}

function handleScreenshot() {
  playerRef.value?.screenshot()
}

function handleFullscreen() {
  playerRef.value?.fullscreen()
}

// PTZ 控制
async function handlePTZ(direction: string) {
  if (!currentMediaStream.value?.cameraId) {
    ElMessage.warning(t('未配置摄像头'))
    return
  }

  try {
    const actionMap: Record<string, string> = {
      UP: 'up',
      DOWN: 'down',
      LEFT: 'left',
      RIGHT: 'right',
      UP_LEFT: 'up',
      UP_RIGHT: 'up',
      DOWN_LEFT: 'down',
      DOWN_RIGHT: 'down'
    }
    const action = actionMap[direction] || 'stop'
    await ptzStart(currentMediaStream.value.cameraId, action as any, ptzSpeed.value)
  } catch (error) {
    console.error('PTZ 控制失败', error)
  }
}

async function handlePTZStop() {
  if (!currentMediaStream.value?.cameraId) return

  try {
    await ptzStop(currentMediaStream.value.cameraId)
  } catch (error) {
    console.error('PTZ 停止失败', error)
  }
}

// 缩放控制
function formatZoomTooltip(val: number) {
  if (val === 0) return t('停止')
  return val > 0 ? `${t('放大')} ${val}` : `${t('缩小')} ${Math.abs(val)}`
}

async function handleZoomChange(val: number) {
  if (!currentMediaStream.value?.cameraId) return

  if (val === 0) {
    await ptzStop(currentMediaStream.value.cameraId)
    return
  }

  const action = val > 0 ? 'zoom_in' : 'zoom_out'
  await ptzStart(currentMediaStream.value.cameraId, action as any, Math.abs(val))
}

async function handleZoomRelease() {
  zoomValue.value = 0
  if (!currentMediaStream.value?.cameraId) return
  await ptzStop(currentMediaStream.value.cameraId)
}

// 缩放按钮控制
async function handleZoomIn() {
  if (!currentMediaStream.value?.cameraId) {
    ElMessage.warning(t('未配置摄像头'))
    return
  }
  try {
    await ptzStart(currentMediaStream.value.cameraId, 'zoom_in' as any, ptzSpeed.value)
  } catch (error) {
    console.error('Zoom in 失败', error)
  }
}

async function handleZoomOut() {
  if (!currentMediaStream.value?.cameraId) {
    ElMessage.warning(t('未配置摄像头'))
    return
  }
  try {
    await ptzStart(currentMediaStream.value.cameraId, 'zoom_out' as any, ptzSpeed.value)
  } catch (error) {
    console.error('Zoom out 失败', error)
  }
}

// 加载预置位列表
async function loadPresets() {
  if (!currentMediaStream.value?.cameraId) {
    ElMessage.warning(t('未配置摄像头'))
    return
  }

  presetsLoading.value = true
  try {
    const res = await getPresets(currentMediaStream.value.cameraId)
    if (res.success && res.data) {
      presetList.value = res.data
    } else {
      presetList.value = []
    }
  } catch (error) {
    console.error('加载预置位失败', error)
    presetList.value = []
  } finally {
    presetsLoading.value = false
  }
}

// 跳转到预置位
async function handleGotoPreset(preset: PresetInfo) {
  if (!currentMediaStream.value?.cameraId) {
    ElMessage.warning(t('未配置摄像头'))
    return
  }

  try {
    activePresetToken.value = preset.token
    const res = await gotoPreset(currentMediaStream.value.cameraId, preset.token)
    if (res.success) {
      ElMessage.success(`${t('已跳转到预置位')}: ${preset.name || preset.token}`)
    } else {
      ElMessage.error(res.errMessage || t('跳转失败'))
    }
  } catch (error) {
    console.error('跳转预置位失败', error)
    ElMessage.error(t('跳转失败'))
  }
}

function handleSizeChange(val: number) {
  pageSize.value = val
  currentPage.value = 1
  getList()
}

function handleCurrentChange(val: number) {
  currentPage.value = val
  getList()
}

onMounted(async () => {
  // 读取 URL 查询参数
  const queryCameraId = route.query.cameraId as string
  const queryAction = route.query.action as string

  if (queryCameraId) {
    searchForm.cameraId = queryCameraId
  }

  // 先加载选项数据
  await loadOptions()
  getList()

  // 如果是创建操作，自动打开新增抽屉
  if (queryAction === 'create') {
    handleAdd()

    // 如果提供了 cameraId，尝试查找摄像头信息以自动填充 lssId
    if (queryCameraId) {
      try {
        const res = await adminListCameras({ cameraId: queryCameraId, size: 1 })
        if (res.success && res.data?.list?.length > 0) {
          const camera = res.data.list[0]
          if (camera.lssId) {
            form.lssId = camera.lssId
            // lssId 变化会触发 watch，加载该 LSS 下的摄像头列表
            // 等待摄像头列表加载完成后再设置 cameraId
            setTimeout(() => {
              form.cameraId = queryCameraId
            }, 500)
          }
        }
      } catch (error) {
        console.error('获取摄像头信息失败', error)
      }
    }
  }
})
</script>

<style lang="scss" scoped>
.page-container {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

.code-editor-wrapper {
}

.search-form {
  flex-shrink: 0;
  margin-bottom: 16px;
  padding: 16px 16px 4px 16px;
  background: #f5f7fa;

  :deep(.el-form-item) {
    margin-bottom: 12px;
    margin-right: 16px;
  }

  :deep(.el-input),
  :deep(.el-select) {
    width: 180px;
  }
}

.table-wrapper {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.pagination-container {
  flex-shrink: 0;
  display: flex;
  justify-content: flex-end;
  padding-top: 16px;
}

:deep(.el-table) {
  --el-table-row-hover-bg-color: #f0f0ff;

  .el-table__row--striped td.el-table__cell {
    background-color: #f8f9fc;
  }

  .el-table__header th {
    background-color: #f5f7fa;
    color: #333;
    font-weight: 600;
  }
}

// 抽屉样式
.stream-drawer {
  :deep(.el-drawer__body) {
    padding: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
  }
}

.drawer-content {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.drawer-header {
  flex-shrink: 0;
  padding: 16px 20px;
  font-size: 16px;
  font-weight: 500;
  color: #303133;
  border-bottom: 1px solid #e5e7eb;
}

.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

.stream-form {
  :deep(.el-form-item) {
    margin-bottom: 18px;
  }

  :deep(.el-form-item__label) {
    color: #606266;
    font-size: 14px;
  }
}

.drawer-footer {
  flex-shrink: 0;
  display: flex;
  justify-content: flex-end;
  padding: 12px 20px;
  border-top: 1px solid #e5e7eb;
  gap: 12px;
}

// 流媒体播放抽屉样式
.media-drawer {
  :deep(.el-drawer__body) {
    padding: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
    background-color: #f5f7fa;
    position: relative;
  }
}

.drawer-close-btn {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  // background-color: rgba(0, 0, 0, 0.5);
  // border-radius: 50%;
  cursor: pointer;
  z-index: 10;
  color: #303133;
  transition: all 0.2s;

  // &:hover {
  //   background-color: rgba(0, 0, 0, 0.7);
  // }
}

.media-drawer-content {
  display: flex;
  height: 100%;
  padding: 16px;
  gap: 16px;
  overflow: hidden;
}

// 左侧视频区域
.video-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background-color: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);

  .video-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    background-color: #fff;
    border-bottom: 1px solid #e5e7eb;

    .header-left {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .title {
      font-size: 16px;
      font-weight: 600;
      color: #303133;
    }
  }

  .player-container {
    flex: 1;
    min-height: 0;
    background-color: #000;
    display: flex;
    align-items: center;
    justify-content: center;

    .player-placeholder {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: #909399;

      p {
        margin-top: 15px;
        font-size: 14px;
      }
    }
  }

  .player-controls {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px;
    background-color: #fff;
    border-top: 1px solid #e5e7eb;
  }
}

// 右侧控制面板
.control-panel {
  width: 280px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow-y: auto;

  .panel-section {
    background-color: #fff;
    border-radius: 8px;
    padding: 16px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);

    .section-title {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 14px;
      font-weight: 600;
      color: #303133;
      margin-bottom: 12px;
      padding-bottom: 8px;
      border-bottom: 1px solid #e5e7eb;
    }
  }
}

// PTZ 方向控制网格
.ptz-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin-bottom: 12px;
}

.ptz-btn {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s;
  color: #606266;

  &:hover {
    background-color: #ecf5ff;
    border-color: #4f46e5;
    color: #4f46e5;
  }

  &:active {
    background-color: #4f46e5;
    color: #fff;
  }

  .el-icon {
    font-size: 18px;
  }

  &.ptz-center {
    background-color: #e5e7eb;

    &:hover {
      background-color: #4f46e5;
      color: #fff;
    }
  }
}

// 缩放按钮
.zoom-buttons {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-bottom: 12px;

  .el-button {
    background-color: #f5f7fa;
    border-color: #dcdfe6;
    color: #606266;

    &:hover {
      background-color: #ecf5ff;
      border-color: #4f46e5;
      color: #4f46e5;
    }
  }
}

// 速度滑块
.speed-slider {
  display: flex;
  align-items: center;
  gap: 12px;

  .label {
    font-size: 12px;
    color: #606266;
    flex-shrink: 0;
  }

  .value {
    font-size: 12px;
    color: #4f46e5;
    width: 30px;
    text-align: right;
  }

  :deep(.el-slider) {
    flex: 1;
  }
}

// 预置位区域
.preset-section {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;

  .preset-list {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 300px;
  }

  .preset-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background-color: #f5f7fa;
    border: 1px solid #dcdfe6;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s;

    &:hover {
      background-color: #ecf5ff;
      border-color: #4f46e5;
    }

    &.active {
      background-color: #4f46e5;
      border-color: #4f46e5;

      .preset-index,
      .preset-name {
        color: #fff;
      }

      .preset-index {
        background-color: rgba(255, 255, 255, 0.2);
      }
    }

    .preset-index {
      width: 28px;
      height: 28px;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: #e5e7eb;
      border-radius: 4px;
      font-size: 12px;
      font-weight: 600;
      color: #4f46e5;
    }

    .preset-name {
      flex: 1;
      font-size: 13px;
      color: #606266;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  :deep(.el-empty) {
    padding: 20px 0;

    .el-empty__description {
      color: #909399;
    }
  }
}
</style>
