<template>
  <div class="camera-config-container">
    <div class="selectBox multi-camera-config" v-id>
      <div class="point-tabs" v-if="isMultiCameraMode">
        <div
          v-for="point in displayPointList"
          :key="point.key"
          class="point-tab"
          :class="{ active: activePoint === point.key }"
          @click="switchPoint(point.key)"
        >
          <span class="tab-name">{{ $t('cameraConfig.pointLabel', { point: point.key }) }}</span>
          <el-tag :type="getPointTagInfo(point.key).type" size="small">
            {{ getPointTagInfo(point.key).text }}
          </el-tag>
        </div>
        <el-button
          type="primary"
          link
          class="refresh-btn"
          :loading="refreshing"
          @click="handleRefresh"
        >
          <el-icon><Refresh /></el-icon>
          {{ $t('cameraConfig.refresh') }}
        </el-button>
      </div>

      <div class="current-point-config">
        <div class="config-body">
          <div v-if="isMultiCameraMode" class="form-item">
            <label class="iso-label">{{ $t('cameraConfig.bindCamera') }}</label>
            <div class="camera-select-wrapper">
              <el-select
                v-model="multiConfig[activePoint].CameraKey"
                :placeholder="$t('cameraConfig.selectCamera')"
                filterable
                clearable
                @change="onCameraChange(activePoint)"
                @focus="ensureCurrentCameraInList"
              >
                <el-option
                  v-for="camera in availableCameras"
                  :key="camera.CameraKey"
                  :label="camera.CameraName"
                  :value="camera.CameraKey"
                  :disabled="!camera.CameraStatus"
                >
                  <span>{{ camera.CameraName }}</span>
                  <el-tag v-if="!camera.CameraStatus" type="danger" size="small" style="margin-left: 8px">{{ $t('cameraConfig.notConnected') }}</el-tag>
                </el-option>
              </el-select>
            </div>
          </div>

          <div class="iso-section">
            <div class="iso-group">
              <span class="iso-label">{{ $t('cameraConfig.photoISO') }}</span>
              <div class="select-wrapper">
                <el-select
                  v-model="multiConfig[activePoint].iso.low"
                  filterable
                  default-first-option
                  :placeholder="$t('cameraConfig.select')"
                  class="iso-select"
                >
                  <el-option
                    v-for="item in iso_options"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </div>
            </div>
            <div class="iso-group">
              <span class="iso-label">{{ $t('cameraConfig.previewISO') }}</span>
              <div class="select-wrapper">
                <el-select
                  v-model="multiConfig[activePoint].iso.high"
                  filterable
                  default-first-option
                  :placeholder="$t('cameraConfig.select')"
                  class="iso-select"
                >
                  <el-option
                    v-for="item in iso_options"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { reactive, onMounted, ref, watch, computed } from 'vue'
import { ElMessage } from 'element-plus'
import client from "@/stores/modules/client";
import icpList from '@/utils/ipc';
import socket from "@/stores/modules/socket.js";
import useUserInfo from '@/stores/modules/user';
import i18n from '@/locales';

const clientStore = client();
const socketStore = socket();
const userInfoStore = useUserInfo();

const props = defineProps({
  camera_configs: {
    type: Object,
    default: () => ({})
  }
})

const emit = defineEmits(['update:camera_configs'])

const isMultiCameraMode = computed(() => userInfoStore.isMultiCameraMode)

const activePoint = ref('A')

const cameraList = ref([])
const refreshing = ref(false)

const pointList = reactive([
  { key: 'A', cameraName: '' },
  { key: 'B', cameraName: '' },
  { key: 'C', cameraName: '' },
])

const getPointStatus = (pointKey) => {
  const config = multiConfig[pointKey]
  if (!config || !config.CameraKey) return 'unset'
  const camera = cameraList.value.find(c => c.CameraKey === config.CameraKey)
  if (!camera) return 'disconnected'
  return camera.CameraStatus ? 'connected' : 'disconnected'
}

const getPointTagInfo = (pointKey) => {
  const status = getPointStatus(pointKey)
  if (status === 'connected') return { text: i18n.global.t('cameraConfig.connected'), type: 'success' }
  if (status === 'disconnected') return { text: i18n.global.t('cameraConfig.notConnected'), type: 'danger' }
  return { text: i18n.global.t('cameraConfig.notSet'), type: 'info' }
}

const multiConfig = reactive({
  A: {
    iso: { low: '100', high: '6400' },
    CameraKey: '',
    CameraName: '',
    iso_options: ['auto', 100, 200, 400, 800, 1600, 3200, 6400, 12800]
  },
  B: {
    iso: { low: '100', high: '6400' },
    CameraKey: '',
    CameraName: '',
    iso_options: ['auto', 100, 200, 400, 800, 1600, 3200, 6400, 12800]
  },
  C: {
    iso: { low: '100', high: '6400' },
    CameraKey: '',
    CameraName: '',
    iso_options: ['auto', 100, 200, 400, 800, 1600, 3200, 6400, 12800]
  }
})

const iso_options = computed(() => {
  return multiConfig[activePoint.value]?.iso_options || ['auto', 100, 200, 400, 800, 1600, 3200, 6400, 12800]
})

const displayPointList = computed(() => {
  if (isMultiCameraMode.value) {
    return pointList
  } else {
    return pointList.filter(p => p.key === 'A')
  }
})

const availableCameras = computed(() => {
  const cameras = cameraList.value || []
  if (!isMultiCameraMode.value) {
    return cameras
  }
  const currentBoundCameraKey = multiConfig[activePoint.value].CameraKey
  return cameras.filter(cam => {
    if (cam.CameraKey === currentBoundCameraKey) {
      return true
    }
    const isBoundByOtherPoint = Object.entries(multiConfig).some(([key, config]) => {
      return key !== activePoint.value && config.CameraKey === cam.CameraKey
    })
    return !isBoundByOtherPoint
  })
})

const switchPoint = (pointKey) => {
  activePoint.value = pointKey
  const cameraKey = multiConfig[pointKey].CameraKey
  if (cameraKey) {
    const camera = cameraList.value.find(c => c.CameraKey === cameraKey)
    if (camera && camera.CameraISO && Array.isArray(camera.CameraISO)) {
      multiConfig[pointKey].iso_options = camera.CameraISO
      const currentLow = multiConfig[pointKey].iso.low
      const currentHigh = multiConfig[pointKey].iso.high
      if (!camera.CameraISO.includes(currentLow)) {
        multiConfig[pointKey].iso.low = camera.CameraISO[0]
      }
      if (!camera.CameraISO.includes(currentHigh)) {
        multiConfig[pointKey].iso.high = camera.CameraISO[0]
      }
    }
  }
}

const fetchCameraList = () => {
  return clientStore.ipc.invoke(icpList.camera.getCameraList).then(result => {
    if (result && result.CameraLists && Array.isArray(result.CameraLists)) {
      cameraList.value = result.CameraLists
      return true
    }
    return false
  }).catch(err => {
    throw err
  })
}

const handleRefresh = async () => {
  if (refreshing.value) return
  refreshing.value = true
  try {
    const ok = await fetchCameraList()
    if (ok) {
      ElMessage.success(i18n.global.t('cameraConfig.cameraConnected'))
    } else {
      ElMessage.warning(i18n.global.t('cameraConfig.noCameraList'))
    }
  } catch {
    ElMessage.error(i18n.global.t('cameraConfig.refreshFailed'))
  } finally {
    refreshing.value = false
  }
}

const fetchIsoConfig = () => {
  clientStore.ipc.removeAllListeners(icpList.socket.message + '_smart_shooter_getinfo');
  socketStore.sendMessage({ type: 'smart_shooter_getinfo' });
  clientStore.ipc.on(icpList.socket.message + '_smart_shooter_getinfo', async (event, result) => {
    if (result.code == 0 && result.data) {
      if (result.data.CameraISO && Array.isArray(result.data.CameraISO)) {
        iso_options.value = result.data.CameraISO
      }
    }
    clientStore.ipc.removeAllListeners(icpList.socket.message + '_smart_shooter_getinfo');
  })
}

const onCameraChange = (pointKey) => {
  const cameraKey = multiConfig[pointKey].CameraKey
  if (cameraKey) {
    const camera = cameraList.value.find(c => c.CameraKey === cameraKey)
    if (camera) {
      multiConfig[pointKey].CameraName = camera.CameraName
      if (camera.CameraISO && Array.isArray(camera.CameraISO)) {
        multiConfig[pointKey].iso_options = camera.CameraISO
        const currentLow = multiConfig[pointKey].iso.low
        const currentHigh = multiConfig[pointKey].iso.high
        if (!camera.CameraISO.includes(currentLow)) {
          multiConfig[pointKey].iso.low = camera.CameraISO[0]
        }
        if (!camera.CameraISO.includes(currentHigh)) {
          multiConfig[pointKey].iso.high = camera.CameraISO[0]
        }
      }
    }
  } else {
    multiConfig[pointKey].CameraName = ''
    multiConfig[pointKey].iso_options = ['auto', 100, 200, 400, 800, 1600, 3200, 6400, 12800]
  }
}

const ensureCurrentCameraInList = () => {
  const currentCameraKey = multiConfig[activePoint.value].CameraKey
  if (!currentCameraKey) return
  const exists = cameraList.value.some(c => c.CameraKey === currentCameraKey)
  if (!exists) {
    cameraList.value.push({
      CameraKey: currentCameraKey,
      CameraName: multiConfig[activePoint.value].CameraName || currentCameraKey,
      CameraStatus: false
    })
  }
}

watch(
  () => cameraList.value,
  () => {
    Object.keys(multiConfig).forEach(pointKey => {
      const config = multiConfig[pointKey]
      if (config.CameraKey) {
        const camera = cameraList.value.find(c => c.CameraKey === config.CameraKey)
        if (camera) {
          config.CameraName = camera.CameraName || config.CameraKey
          if (camera.CameraISO && Array.isArray(camera.CameraISO)) {
            config.iso_options = camera.CameraISO
            if (!camera.CameraISO.includes(config.iso.low)) {
              config.iso.low = camera.CameraISO[0]
            }
            if (!camera.CameraISO.includes(config.iso.high)) {
              config.iso.high = camera.CameraISO[0]
            }
          }
        }
      }
    })
  },
  { deep: true }
)

watch(multiConfig, (newVal) => {
  const isoConfig = {}
  Object.keys(newVal).forEach(key => {
    isoConfig[key] = {
      iso: newVal[key].iso,
      CameraKey: newVal[key].CameraKey,
      CameraName: newVal[key].CameraName
    }
  })
  emit('update:camera_configs', {
    iso_config: isoConfig,
  })
}, { deep: true })

onMounted(() => {
  if (props.camera_configs.iso_config) {
    const config = props.camera_configs.iso_config
    if (config.low !== undefined || config.high !== undefined) {
      multiConfig.A.iso.low = String(config.low || '100')
      multiConfig.A.iso.high = String(config.high || '6400')
    } else {
      Object.keys(config).forEach(key => {
        if (multiConfig[key] !== undefined) {
          if (config[key].iso) {
            multiConfig[key].iso.low = config[key].iso.low || '100'
            multiConfig[key].iso.high = config[key].iso.high || '6400'
          }
          if (config[key].CameraKey) {
            multiConfig[key].CameraKey = config[key].CameraKey
            multiConfig[key].CameraName = config[key].CameraName || ''
          }
        }
      })
    }
  }

  activePoint.value = 'A'
  fetchCameraList()
})

const save = () => {
  const current = multiConfig[activePoint.value]
  const isEmpty = (v) => v === undefined || v === null || v === ''

  if (isEmpty(current.iso.low)) {
    ElMessage.error('请选择拍照ISO')
    return false
  }
  if (isEmpty(current.iso.high)) {
    ElMessage.error('请选择预览ISO')
    return false
  }

  const lowNum = Number(current.iso.low)
  const highNum = Number(current.iso.high)
  if (!Number.isNaN(lowNum) && lowNum <= 0) {
    ElMessage.error('拍照ISO必须大于0')
    return false
  }
  if (!Number.isNaN(highNum) && highNum <= 0) {
    ElMessage.error('预览ISO必须大于0')
    return false
  }

  return true
}

defineExpose({ save })
</script>

<style lang="scss" scoped>
.selectBox {
  padding-top: 10px;
  padding-bottom: 50px;
}

.multi-camera-config {
  padding-top: 20px;
  padding-left: 100px;
}

.point-tabs {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}

.point-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  background: #F5F7FA;
  border: 2px solid #E4E7ED;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.3s;

  &:hover {
    border-color: #C0C4CC;
  }

  &.active {
    background: #ECF5FF;
    border-color: #409EFF;
  }

  .tab-name {
    font-weight: bold;
    color: #303133;
  }
}

.refresh-btn {
  margin-left: auto;
}

.current-point-config {
  overflow: hidden;
  max-width: 500px;

  .config-body {
    padding: 24px 20px;

    .form-item {
      margin-bottom: 20px;

      label {
        display: block;
        margin-bottom: 8px;
        font-size: 14px;
      }

      .camera-select-wrapper {
        max-width: 200px;
      }
    }

    .iso-section {
      display: flex;
      gap: 20px;
      flex-wrap: wrap;
    }

    .iso-group {
      display: flex;
      align-items: center;
      gap: 15px;

      .iso-label {
        min-width: 125px;
        font-size: 14px;
        text-align: right;
        color: #1A1A1A;
      }
    }
  }
}

.select-wrapper {
  :deep(.el-input__inner) {
    border-radius: 6px;
  }
}

:deep(.el-select) {
  width: 100%;
}

:deep(.camera-select-wrapper .el-select) {
  width: 300px;
}
</style>
