<template>
  <cacp-search-layout>
    <template #search>
      <cacp-search-panel-layout
        :model="state.queryData"
        ref="queryFormRef"
        label-position="left"
        label-width="auto"
        :gutter="30"
        :colSpan="6"
      >
        <el-form-item label="表名称" prop="tableName">
          <el-input
            v-model="state.queryData.tableName"
            placeholder="请输入表名称"
            clearable
            @keyup.enter="onSearch"
          />
        </el-form-item>
        <el-form-item label="表描述" prop="tableComment">
          <el-input
            v-model="state.queryData.tableComment"
            placeholder="请输入表描述"
            clearable
            @keyup.enter="onSearch"
          />
        </el-form-item>
        <el-form-item label="创建时间">
          <el-date-picker
            v-model="state.dateRange"
            style="width: 100%"
            value-format="YYYY-MM-DD"
            type="daterange"
            range-separator="-"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            @change="onDateChange"
          />
        </el-form-item>
        <template #buttonGroup>
          <el-button type="primary" @click="onSearch">查询</el-button>
          <el-button type="info" @click="onReset">重置</el-button>
        </template>
      </cacp-search-panel-layout>
    </template>

    <cacp-complex-table
      :actions="actions"
      :data="tableData"
      :pagination="tablePagination"
      @selection-change="handleSelectionChange"
      @on-page-change="onPageChange"
      @on-size-change="onSizeChange"
      :loading="loading"
    >
      <el-table-column type="selection" align="center" width="55" />
      <el-table-column label="序号" width="50" align="center">
        <template #default="{ $index }">
          <span>{{ (state.queryData.pageNum - 1) * state.queryData.pageSize + $index + 1 }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="表名称"
        align="center"
        prop="tableName"
        :show-overflow-tooltip="true"
      />
      <el-table-column
        label="实体"
        align="center"
        prop="className"
        :show-overflow-tooltip="true"
      />
      <el-table-column
        label="表描述"
        align="center"
        prop="tableComment"
        :show-overflow-tooltip="true"
        width="220"
      />
      <el-table-column
        label="创建时间"
        align="center"
        prop="createTime"
        width="160"
      />
      <el-table-column
        label="更新时间"
        align="center"
        prop="updateTime"
        width="160"
      />
<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="{ row }">
          <el-button
            type="text"
            size="small"
            @click="onPreview(row)"
            v-has-permi="['tool:gen:preview']"
          >
            预览
          </el-button>
          <el-button
            type="text"
            size="small"
            @click="onEditTable(row)"
            v-has-permi="['tool:gen:edit']"
          >
            编辑
          </el-button>
          <el-button
            type="text"
            size="small"
            @click="onDelete(row)"
            v-has-permi="['tool:gen:remove']"
          >
            删除
          </el-button>
          <el-button
            type="text"
            size="small"
            @click="onSynchDb(row)"
            v-has-permi="['tool:gen:edit']"
          >
            同步
          </el-button>
          <el-button
            type="text"
            size="small"
            @click="onGenTable(row)"
          >
            生成代码
          </el-button>
        </template>
      </el-table-column>-->
    </cacp-complex-table>

    <!-- 代码预览对话框 -->
    <el-dialog
      :title="state.preview.title"
      v-model="state.preview.open"
      width="80%"
      top="5vh"
      append-to-body
      class="scrollbar"
      @closed="onPreviewClose"
    >
      <el-tabs v-model="state.preview.activeName" type="border-card">
        <el-tab-pane
          v-for="(value, key) in state.preview.data"
          :label="getTabLabel(key)"
          :name="getTabName(key)"
          :key="key"
        >
          <template #label>
            <span class="tab-label">{{ getTabLabel(key) }}</span>
          </template>
          <div class="code-header">
            <el-tooltip content="复制代码" placement="top">
              <el-button
                @click="onCopy(value)"
                size="small"
                text
              >
                复制
              </el-button>
            </el-tooltip>
          </div>
          <div class="code-container">
            <pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-dialog>

    <!-- 子组件 -->
    <ImportTable ref="importRef" @ok="onSearch" />
  </cacp-search-layout>
</template>

<script lang="ts" setup>
import { onMounted, reactive, ref, computed, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import config from '@/config'
import type { GenTable, GenTableQuery } from '@/types/gen/GenTable'

import {
  useComplexTable,
  type SearchPanelLayoutInstance,
  type TableAction,
  useLoading, SuccessResultCode
} from '@cacp/ui'

import {
  getList,
  previewTable,
  remove,
  synchDb,
  batchGenCode
} from '@/apis/gen/gen'

import ImportTable from './importTable.vue'
import hljs from 'highlight.js/lib/core'
import javascript from 'highlight.js/lib/languages/javascript'
import xml from 'highlight.js/lib/languages/xml'
import json from 'highlight.js/lib/languages/json'
import sql from 'highlight.js/lib/languages/sql'
import java from 'highlight.js/lib/languages/java'
import css from 'highlight.js/lib/languages/css'

// 注册语言
hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('xml', xml)
hljs.registerLanguage('json', json)
hljs.registerLanguage('sql', sql)
hljs.registerLanguage('java', java)
hljs.registerLanguage('css', css)

// 路由
const route = useRoute()
const router = useRouter()

// Refs
const queryFormRef = ref<SearchPanelLayoutInstance>()
const importRef = ref<InstanceType<typeof ImportTable>>()

// 加载状态
const { loading, setLoading } = useLoading()

// 表格 Hook
const tableHooks = useComplexTable<GenTable>(config)
const { tableData, tablePagination, setPagination, setPageIndex, setPageSizes } = tableHooks

// 响应式数据
interface PreviewData {
  open: boolean
  title: string
  data: Record<string, string>
  activeName: string
}

interface State {
  queryData: GenTableQuery & {
    sort?: string
    order?: string
    beginTime?: string
    endTime?: string
    pageNum: number
    pageSize: number
    tableName?: string
    tableComment?: string
  }
  preview: PreviewData
  dateRange: string[]
  selectedRows: GenTable[]
}

const state = reactive<State>({
  queryData: {
    pageNum: 1,
    pageSize: 10,
    tableName: undefined,
    tableComment: undefined,
    sort: undefined,
    order: undefined
  },
  preview: {
    open: false,
    title: '代码预览',
    data: {},
    activeName: 'domain.java'
  },
  dateRange: [],
  selectedRows: []
})

// 计算属性
const ids = computed(() => state.selectedRows.map(item => item.tableId))
const tableNames = computed(() => state.selectedRows.map(item => item.tableName))

// 表格操作按钮配置
const actions = <Array<TableAction>>[
  {
    key: 'gen',
    text: '生成',
    onclick: onGenTable,
    limit: 'none',
    type: 'primary',
  },
/*  {
    key: 'create',
    text: '创建',
    onclick: onCreateTable,
    limit: 'none',
    type: 'primary',
    plain: true,
    icon: 'Plus'
  },*/
  {
    key: 'import',
    text: '导入',
    onclick: onImportTable,
    limit: 'none',
    type: 'info',
  },
  {
    key: 'preview',
    text: '预览',
    onclick: onPreview,
    limit:'one',
    // limit: permissionStatus('one', 'ANALYZE_NEWDECLAREDGOODS_EDIT_BT'),
    type: 'primary'
  },
  {
    key: 'edit',
    text: '修改',
    onclick: onEditTable,
    limit: 'one',
    type: 'success',
  },
  {
    key: 'delete',
    text: '删除',
    onclick: onDelete,
    limit: 'one',
    type: 'danger',
  },
  {
    key: 'synchDb',
    text: '同步',
    onclick: onSynchDb,
    limit: 'one',
    type: 'success',
  },
  {
    key: 'genOne',
    text: '生成',
    onclick: onGenTable,
    limit: 'one',
    type: 'primary',
  },
]

// 搜索方法
const onSearch = () => {
  setPageIndex(1)
  onLoadData()
}

// 重置方法
const onReset = () => {
  queryFormRef.value?.resetFields()
  state.dateRange = []
  state.queryData.sort = undefined
  state.queryData.order = undefined
  onPageChange(1)
}

// 日期范围变化
const onDateChange = (value: string[]) => {
  state.dateRange = value
}

// 每页显示条数变化
const onSizeChange = (size: number) => {
  setPageSizes(size)
  onLoadData()
}

// 翻页查询
const onPageChange = (currentPage: number) => {
  setPageIndex(currentPage)
  onLoadData()
}

// 多选框选中数据
function handleSelectionChange(selection: GenTable[]) {
  state.selectedRows = selection
}

// 生成代码操作
async function onGenTable(row?: GenTable) {
  const targetTableNames = row?.tableName || tableNames.value.join(',')

  if (!targetTableNames) {
    ElMessage.error('请选择要生成的数据')
    return
  }

  try {
    setLoading(true)
    const response = await batchGenCode(targetTableNames)

    if (response.data instanceof Blob && response.data.size > 0) {
      const url = window.URL.createObjectURL(response.data)
      const link = document.createElement('a')
      link.href = url
      link.download = targetTableNames.includes(',') ? 'codes.zip' : `${targetTableNames}.zip`
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(url)
      ElMessage.success('代码生成成功')
    } else {
      throw new Error('响应不是有效的文件数据')
    }
  } catch (error: any) {
    console.error('生成代码失败:', error)
    ElMessage.error('生成代码失败: ' + (error.message || '未知错误'))
  } finally {
    setLoading(false)
  }
}

// 同步数据库操作
async function onSynchDb(row: GenTable) {
  try {
    await ElMessageBox.confirm(
      `确认要强制同步"${row.tableName}"表结构吗？`,
      '系统提示',
      {
        type: 'warning',
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }
    )

    const res = await synchDb(row.tableName)
    if (res.code === SuccessResultCode) {
      ElMessage.success('同步成功')
      onLoadData()
    } else {
      ElMessage.error(res.message || '同步失败')
    }
  } catch (error) {
    console.error('操作失败:', error)
    ElMessage.error('同步失败')
  }
}

// 打开导入表弹窗
function onImportTable() {
  importRef.value?.show()
}

// 预览按钮
async function onPreview(row: GenTable) {
  try {
    const res = await previewTable(row.tableId)
    if (res.code === SuccessResultCode) {
      state.preview.data = res.data
      state.preview.open = true
      state.preview.activeName = Object.keys(res.data)[0]?.split('/').pop()?.split('.vm')[0] || 'domain.java'
    } else {
      ElMessage.error(res.message || '预览失败')
    }
  } catch (error) {
    ElMessage.error('预览失败')
    console.error('预览失败:', error)
  }
}

// 关闭预览
function onPreviewClose() {
  state.preview.data = {}
  state.preview.activeName = 'domain.java'
}

// 获取标签页名称
function getTabName(key: string) {
  const lastSlashIndex = key.lastIndexOf('/')
  const vmIndex = key.indexOf('.vm')
  return key.substring(lastSlashIndex + 1, vmIndex)
}

// 获取标签页显示标签
function getTabLabel(key: string) {
  return getTabName(key)
}

// 高亮显示代码
function highlightedCode(code: string, key: string) {
  const vmName = getTabName(key)
  const language = vmName.substring(vmName.lastIndexOf('.') + 1)

  try {
    const result = hljs.highlight(code || '', {
      language: getLanguageAlias(language)
    })
    return result.value || '&nbsp;'
  } catch (error) {
    console.error( error)
    return code || '&nbsp;'
  }
}

// 获取语言别名
function getLanguageAlias(language: string): string {
  const aliases: Record<string, string> = {
    'java': 'java',
    'xml': 'xml',
    'html': 'xml',
    'js': 'javascript',
    'javascript': 'javascript',
    'json': 'json',
    'sql': 'sql',
    'css': 'css',
    'vue': 'xml'
  }
  return aliases[language] || 'plaintext'
}

// 复制代码
async function onCopy(code: string) {
  try {
    await navigator.clipboard.writeText(code)
    ElMessage.success('复制成功')
  } catch (error) {
    console.error('复制失败:', error)
    ElMessage.error('复制失败')
  }
}

// 修改按钮操作
function onEditTable(row?: GenTable) {
  const tableId = row?.tableId || ids.value[0]
  const tableName = row?.tableName || tableNames.value[0]

  router.push({
    name: 'GenEdit',
    params: { tableId },
    query: {
      pageNum: state.queryData.pageNum.toString(),
      tableName
    }
  })
}

// 删除按钮操作
async function onDelete(row?: GenTable) {
  const tableIds = row?.tableId || ids.value

  try {
    await ElMessageBox.confirm(
      `是否确认删除表编号为"${Array.isArray(tableIds) ? tableIds.join(',') : tableIds}"的数据项？`,
      '系统提示',
      {
        type: 'warning',
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }
    )

    const res = await remove(tableIds)
    if (res.code === SuccessResultCode) {
      ElMessage.success('删除成功')
      onLoadData()
    } else {
      ElMessage.error(res.message || '删除失败')
    }
  } catch (error) {
    // 用户取消操作
    console.log(error)
  }
}

// 数据查询
async function onLoadData() {
  setLoading(true)
  try {
    const query = {
      ...state.queryData,
      pageIndex: tablePagination.currentPage,
      pageSize: tablePagination.pageSize
    }
    const res = await getList(query)

    if (res.code === SuccessResultCode) {
      setPagination(res.data)
    } else {
      ElMessage.error(res.message || '获取数据失败')
    }
  } catch (error) {
    ElMessage.error('网络错误，请稍后重试')
    console.error('获取表列表失败:', error)
  } finally {
    setLoading(false)
  }
}

// 监听路由变化
watch(
  () => route.query,
  (newQuery) => {
    const time = newQuery.t as string
    if (time) {
      state.queryData.pageNum = Number(newQuery.pageNum) || 1
      onLoadData()
    }
  },
  { immediate: true }
)

// 组件挂载时加载数据
onMounted(() => {
  onLoadData()
})
</script>

<style scoped>
.scrollbar {
  max-height: 70vh;
  overflow-y: auto;
}

.code-header {
  display: flex;
  justify-content: flex-end;
  padding: 8px 0;
  border-bottom: 1px solid #e8e8e8;
  margin-bottom: 12px;
}

.code-container {
  background: #f8f9fa;
  border-radius: 4px;
  padding: 16px;
  overflow-x: auto;
}

.hljs {
  background: transparent !important;
  padding: 0 !important;
  font-family: 'JetBrains Mono', 'Fira Code', Consolas, 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.tab-label {
  font-weight: 500;
}

:deep(.el-table .small-padding) {
  padding: 8px 0;
}

:deep(.el-tabs__content) {
  position: relative;
}

:deep(.el-tabs--border-card > .el-tabs__content) {
  padding: 16px;
}
</style>
