<script lang="ts" setup>
import {
  WebtopoProjectApi,
  type WebtopoProjectCopyReqVO,
  type WebtopoProjectCreateReqVO,
  type WebtopoProjectPageReqVO,
  type WebtopoProjectUpdateReqVO,
  type WebtopoProjectVO
} from '@/api/pms/maotu'
import { IotDeviceApi } from '@/api/pms/device'
import { useUserStore } from '@/store/modules/user'
import { useDebounceFn } from '@vueuse/core'
import dayjs from 'dayjs'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'

defineOptions({ name: 'MaotuList' })

const router = useRouter()

const id = useUserStore().getUser.deptId
const deptId = id

const loading = ref(false)
const list = ref<WebtopoProjectVO[]>([])
const total = ref(0)

const initQuery: WebtopoProjectPageReqVO = {
  pageNo: 1,
  pageSize: 12,
  deptId: id,
  projectName: ''
}

const query = ref<WebtopoProjectPageReqVO>({ ...initQuery })

type FormMode = 'create' | 'config' | 'copy'
type ProjectForm = Partial<WebtopoProjectUpdateReqVO>

interface DeviceOption {
  label: string
  value: number
}

const createVisible = ref(false)
const createLoading = ref(false)
const deviceLoading = ref(false)
const formRef = ref<FormInstance>()
const formMode = ref<FormMode>('create')
const deviceOptions = ref<DeviceOption[]>([])
const createForm = ref<ProjectForm>({
  projectName: '',
  linkedDeviceIds: [],
  remark: ''
})

const rules: FormRules = {
  projectName: [{ required: true, message: '请输入项目名称', trigger: ['blur', 'change'] }]
}

const loadList = useDebounceFn(async () => {
  loading.value = true
  try {
    const data = await WebtopoProjectApi.getWebtopoProjectPage(query.value)
    if (Array.isArray(data)) {
      list.value = data
      total.value = data.length
      return
    }

    list.value = data?.list || []
    total.value = data?.total || 0
  } finally {
    loading.value = false
  }
}, 200)

function getChineseName(value?: string) {
  return (value || '').split('~~')[0]
}

function formatDeviceLabel(item: any) {
  const code = item.deviceCode || ''
  const name = getChineseName(item.deviceName || item.label)
  return [code, name].filter(Boolean).join(' - ')
}

function getLinkedDeviceIds(row: WebtopoProjectVO) {
  return row.linkedDeviceIds || row.linkedDevices?.map((item) => item.id) || []
}

async function loadDeviceOptions(deptId?: number) {
  if (!deptId) {
    deviceOptions.value = []
    return
  }

  deviceLoading.value = true
  try {
    const data = await IotDeviceApi.simpleDevices({ deptId })
    deviceOptions.value = (Array.isArray(data) ? data : []).map((item: any) => ({
      label: formatDeviceLabel(item),
      value: item.id
    }))
  } finally {
    deviceLoading.value = false
  }
}

function handleSizeChange(val: number) {
  query.value.pageSize = val
  handleQuery()
}

function handleCurrentChange(val: number) {
  query.value.pageNo = val
  loadList()
}

function handleQuery(setPage = true) {
  if (setPage) {
    query.value.pageNo = 1
  }
  loadList()
}

function resetQuery() {
  query.value = { ...initQuery }
  handleQuery()
}

async function openCreate() {
  formMode.value = 'create'
  createForm.value = {
    id: undefined,
    projectName: '',
    linkedDeviceIds: [],
    remark: ''
  }
  deviceOptions.value = []
  createVisible.value = true
  await loadDeviceOptions(deptId)
  await nextTick()
  formRef.value?.clearValidate()
}

async function openConfig(row: WebtopoProjectVO) {
  formMode.value = 'config'
  createForm.value = {
    id: row.id,
    projectName: row.projectName,
    linkedDeviceIds: getLinkedDeviceIds(row),
    remark: row.remark
  }
  deviceOptions.value = []
  createVisible.value = true
  await loadDeviceOptions(deptId)
  await nextTick()
  formRef.value?.clearValidate()
}

async function openCopy(row: WebtopoProjectVO) {
  formMode.value = 'copy'
  createForm.value = {
    id: row.id,
    projectName: `${row.projectName || ''}副本`,
    linkedDeviceIds: getLinkedDeviceIds(row),
    remark: row.remark
  }
  deviceOptions.value = []
  createVisible.value = true
  await loadDeviceOptions(deptId)
  await nextTick()
  formRef.value?.clearValidate()
}

function handleCreateClose() {
  createVisible.value = false
}

async function submitCreate() {
  if (!formRef.value || deviceLoading.value) return

  try {
    createLoading.value = true
    await formRef.value.validate()
    const data: WebtopoProjectCreateReqVO = {
      projectName: createForm.value.projectName!,
      linkedDeviceIds: createForm.value.linkedDeviceIds || [],
      remark: createForm.value.remark
    }
    const res = await WebtopoProjectApi.createWebtopoProject(data)
    const projectId = typeof res === 'number' ? res : res?.data

    if (!projectId) {
      ElMessage.error('新增成功，但未返回项目 ID')
      return
    }

    ElMessage.success('新增成功')
    handleCreateClose()
    router.push(`/maotu/edit/${projectId}`)
  } finally {
    createLoading.value = false
  }
}

async function submitConfig() {
  if (!formRef.value || !createForm.value.id || deviceLoading.value) return

  try {
    createLoading.value = true
    await formRef.value.validate()
    const data = { ...createForm.value } as WebtopoProjectUpdateReqVO
    await WebtopoProjectApi.updateWebtopoProject(data)
    ElMessage.success('更新成功')
    handleCreateClose()
    loadList()
  } finally {
    createLoading.value = false
  }
}

async function submitCopy() {
  if (!formRef.value || !createForm.value.id || deviceLoading.value) return

  try {
    createLoading.value = true
    await formRef.value.validate()
    const data: WebtopoProjectCopyReqVO = {
      id: createForm.value.id,
      projectName: createForm.value.projectName!,
      remark: createForm.value.remark
    }
    await WebtopoProjectApi.copyWebtopoProject(data)
    ElMessage.success('复制成功')
    handleCreateClose()
    loadList()
  } finally {
    createLoading.value = false
  }
}

function submitForm() {
  if (formMode.value === 'config') {
    submitConfig()
    return
  }

  if (formMode.value === 'copy') {
    submitCopy()
    return
  }

  submitCreate()
}

function formatCreateTime(value?: number | string) {
  if (!value) return '-'
  const time = typeof value === 'number' && value.toString().length === 10 ? value * 1000 : value
  return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
}

function getLinkedDeviceCount(row: WebtopoProjectVO) {
  return getLinkedDeviceIds(row).length
}

function handleEdit(row: WebtopoProjectVO) {
  const routeInfo = router.resolve(`/maotu/edit/${row.id}`)
  window.open(routeInfo.href, '_blank')
}

function handlePreview(row: WebtopoProjectVO) {
  const routeInfo = router.resolve(`/maotu/preview/${row.id}`)
  window.open(routeInfo.href, '_blank')
}

function handleConfig(row: WebtopoProjectVO) {
  openConfig(row)
}

function handleCopy(row: WebtopoProjectVO) {
  openCopy(row)
}

function getDialogTitle() {
  if (formMode.value === 'config') {
    return '配置关联设备'
  }

  if (formMode.value === 'copy') {
    return '复制组态项目'
  }

  return '新建组态项目'
}

const isDeviceSelectDisabled = computed(() => deviceLoading.value || formMode.value === 'copy')

watch(
  [() => query.value.deptId, () => query.value.projectName],
  () => {
    handleQuery()
  },
  { immediate: true }
)
</script>

<template>
  <div
    class="grid grid-cols-[auto_1fr] grid-rows-[62px_1fr] gap-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
    <DeptTreeSelect
      :top-id="156"
      :deptId="deptId"
      v-model="query.deptId"
      :show-title="false"
      class="row-span-2" />

    <el-form
      size="default"
      @submit.prevent="handleQuery()"
      class="filter-form bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 gap-8 flex items-center justify-between">
      <div class="flex items-center gap-8">
        <el-form-item label="组态名称">
          <el-input
            v-model="query.projectName"
            clearable
            class="!w-240px"
            placeholder="请输入组态名称"
            @keydown.enter.prevent="handleQuery()" />
        </el-form-item>
      </div>
      <el-form-item>
        <el-button type="primary" @click="handleQuery()">
          <Icon icon="ep:search" class="mr-5px" /> 搜索
        </el-button>
        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
        <el-button type="primary" plain @click="openCreate">
          <Icon icon="ep:plus" class="mr-5px" /> 新建
        </el-button>
      </el-form-item>
    </el-form>

    <div class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow flex flex-col min-h-0">
      <div class="flex-1 relative">
        <el-auto-resizer class="absolute">
          <template #default="{ height }">
            <el-scrollbar v-loading="loading" :height="height" view-class="p-4 min-h-full">
              <div
                v-if="!loading && !list.length"
                class="h-full min-h-[360px] flex flex-col items-center justify-center text-gray-400">
                <div class="i-lucide-inbox text-5xl mb-4 op-50"></div>
                <p class="text-sm font-medium">暂无组态项目</p>
                <p class="text-xs mt-1 op-60">尝试调整组织或搜索条件</p>
              </div>

              <div
                v-else
                class="grid grid-cols-[repeat(auto-fill,minmax(300px,1fr))] auto-rows-max content-start gap-4">
                <div
                  v-for="item in list"
                  :key="item.id"
                  class="group bg-white dark:bg-[#262727] rounded-lg shadow-sm border border-gray-100 dark:border-gray-700 hover:shadow-[0_10px_24px_rgba(15,23,42,0.12)] hover:-translate-y-1 transition-all duration-300 overflow-hidden">
                  <div class="relative h-170px bg-[var(--el-fill-color-light)] overflow-hidden">
                    <el-image
                      v-if="item.thumbnail"
                      :src="item.thumbnail"
                      fit="cover"
                      class="w-full h-full transition-transform duration-500 group-hover:scale-105"
                      lazy>
                      <template #error>
                        <div
                          class="h-full flex flex-col items-center justify-center text-12px text-[var(--el-text-color-secondary)]">
                          <Icon icon="ep:picture" class="text-28px mb-2 op-60" />
                          缩略图加载失败
                        </div>
                      </template>
                    </el-image>
                    <div
                      v-else
                      class="h-full flex flex-col items-center justify-center text-12px text-[var(--el-text-color-secondary)] bg-gradient-to-br from-gray-50 to-gray-100 dark:from-[#252728] dark:to-[#1d1e1f]">
                      <Icon icon="ep:picture" class="text-32px mb-2 op-60" />
                      暂无缩略图
                    </div>

                    <div
                      class="absolute left-3 top-3 flex items-center gap-1.5 rounded-full bg-black/45 backdrop-blur px-2.5 py-1 text-xs text-white">
                      <Icon icon="ep:cpu" />
                      {{ getLinkedDeviceCount(item) }} 台设备
                    </div>
                  </div>

                  <div class="p-4">
                    <div class="flex items-start justify-between gap-3">
                      <el-tooltip effect="dark" :content="item.projectName" placement="top-start">
                        <div
                          class="text-16px font-600 text-gray-800 dark:text-gray-100 truncate"
                          :title="item.projectName">
                          {{ item.projectName || '-' }}
                        </div>
                      </el-tooltip>
                      <!-- <el-tag size="small" effect="light" type="info" class="shrink-0">
                        ID {{ item.id }}
                      </el-tag> -->
                    </div>

                    <div class="mt-3 grid gap-2 text-12px text-gray-500 dark:text-gray-400">
                      <div class="flex items-center justify-between gap-3">
                        <span class="flex items-center gap-1.5 text-gray-400">
                          <Icon icon="ep:clock" /> 创建时间
                        </span>
                        <span class="font-medium text-gray-600 dark:text-gray-300">
                          {{ formatCreateTime(item.createTime) }}
                        </span>
                      </div>
                    </div>

                    <div
                      class="mt-3 text-12px leading-20px text-gray-400 dark:text-gray-500 line-clamp-2"
                      :title="item.remark">
                      {{ item.remark || '暂无备注' }}
                    </div>
                  </div>

                  <div
                    class="px-4 py-3 bg-gray-50/80 dark:bg-[#1d1e1f] flex items-center justify-end gap-3 group-hover:bg-blue-50/40 dark:group-hover:bg-blue-900/10 transition-colors">
                    <el-button size="small" type="primary" link @click="handleEdit(item)">
                      <Icon icon="ep:edit" class="mr-4px" /> 编辑
                    </el-button>
                    <el-button size="small" type="primary" link @click="handlePreview(item)">
                      <Icon icon="ep:view" class="mr-4px" /> 预览
                    </el-button>
                    <el-button size="small" type="primary" link @click="handleCopy(item)">
                      <Icon icon="ep:copy-document" class="mr-4px" /> 复制
                    </el-button>
                    <el-button size="small" type="primary" link @click="handleConfig(item)">
                      <Icon icon="ep:setting" class="mr-4px" /> 配置
                    </el-button>
                  </div>
                </div>
              </div>
            </el-scrollbar>
          </template>
        </el-auto-resizer>
      </div>

      <div class="h-10 mt-4 mb-4 px-4 flex items-center justify-end shrink-0">
        <el-pagination
          size="default"
          v-show="total > 0"
          v-model:current-page="query.pageNo"
          v-model:page-size="query.pageSize"
          :background="true"
          :page-sizes="[12, 20, 30, 50, 100]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange" />
      </div>
    </div>
  </div>

  <el-dialog
    v-model="createVisible"
    :title="getDialogTitle()"
    width="560px"
    :close-on-click-modal="false"
    destroy-on-close>
    <el-form
      ref="formRef"
      v-loading="deviceLoading"
      element-loading-text="设备选项加载中..."
      :model="createForm"
      :rules="rules"
      label-position="top"
      require-asterisk-position="right"
      size="default">
      <el-form-item label="项目名称" prop="projectName">
        <el-input v-model="createForm.projectName" clearable placeholder="请输入项目名称" />
      </el-form-item>

      <el-form-item label="绑定设备" prop="linkedDeviceIds">
        <el-select
          v-model="createForm.linkedDeviceIds"
          multiple
          filterable
          clearable
          collapse-tags
          collapse-tags-tooltip
          :max-collapse-tags="3"
          :loading="deviceLoading"
          :disabled="isDeviceSelectDisabled"
          class="w-full"
          :placeholder="deviceLoading ? '设备选项加载中...' : '请选择绑定设备'">
          <el-option
            v-for="item in deviceOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value" />
        </el-select>
      </el-form-item>

      <el-form-item label="备注" prop="remark">
        <el-input
          v-model="createForm.remark"
          type="textarea"
          :autosize="{ minRows: 3, maxRows: 6 }"
          show-word-limit
          :maxlength="500"
          resize="none"
          placeholder="请输入备注" />
      </el-form-item>
    </el-form>

    <template #footer>
      <el-button @click="handleCreateClose">取消</el-button>
      <el-button
        type="primary"
        :loading="createLoading"
        :disabled="deviceLoading"
        @click="submitForm">
        保存
      </el-button>
    </template>
  </el-dialog>
</template>

<style scoped>
.filter-form :deep(.el-form-item) {
  margin-bottom: 0;
}

:deep(.el-pagination) {
  margin-top: 0;
}
</style>
