<script setup lang="ts">
import type { TreeNode } from './composables/use-connection-tree';

import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue';

import {
  EasyFlowButton,
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from '@easyflow-core/shadcn-ui';

import {
  ElDropdown,
  ElDropdownItem,
  ElDropdownMenu,
  ElEmpty,
  ElMessageBox,
} from 'element-plus';

import ConnectionTree from './components/ConnectionTree.vue';
import ExcelActionDrawer from './components/ExcelActionDrawer.vue';
import SourceFormDrawer from './components/SourceFormDrawer.vue';
import TableDetailView from './components/TableDetailView.vue';
import TableListView from './components/TableListView.vue';
import { useConnectionTree } from './composables/use-connection-tree';
import { useDatacenterExcel } from './composables/use-datacenter-excel';
import { useDatacenterSources } from './composables/use-datacenter-sources';
import { useDatacenterTables } from './composables/use-datacenter-tables';

const sourceFormRef = ref<InstanceType<typeof SourceFormDrawer>>();
const excelActionRef = ref<InstanceType<typeof ExcelActionDrawer>>();
const sourceFormVisible = ref(false);
const excelActionVisible = ref(false);
const workspaceRef = ref<HTMLElement>();
const workspaceHeight = ref('100%');

const {
  sources,
  selectedSourceId,
  selectedSource,
  loading,
  saving,
  testing,
  loadSources,
  removeSource,
  saveSource,
  testConnection,
  markSourceRuntimeUnavailable,
  clearSourceRuntimeUnavailable,
} = useDatacenterSources();

const {
  sourceTables,
  managedTables,
  schema,
  previewRows,
  jobs,
  sourceUnavailable,
  selectedCatalogId,
  selectedTableId,
  selectedTable,
  previewLoading,
  loadTableRuntime,
  syncSourceContext,
  batchRegisterTables,
  batchRemoveTables,
  saveDescriptions,
} = useDatacenterTables(selectedSourceId, {
  markSourceRuntimeUnavailable,
  clearSourceRuntimeUnavailable,
});

async function reloadAll(options?: {
  focus?: 'source' | 'table';
  resetTable?: boolean;
}) {
  await loadSources();
  if (!selectedSourceId.value) {
    selectedCatalogId.value = null;
    selectedTableId.value = null;
    selectedNodeKey.value = '';
    viewMode.value = 'empty';
    await syncSourceContext();
    return;
  }
  if (options?.resetTable) {
    selectedTableId.value = null;
  }
  await syncSourceContext();
  if (options?.focus === 'table' && selectedTable.value) {
    selectedNodeKey.value = `table-${selectedTable.value.id}`;
    viewMode.value = 'detail';
    return;
  }
  selectedNodeKey.value = `source-${selectedSourceId.value}`;
  viewMode.value = 'list';
}

const {
  actionLoading,
  pendingUploadFile,
  splitForm,
  mergeForm,
  deriveForm,
  exportForm,
  resetSplitForm,
  resetMergeForm,
  resetDeriveForm,
  resetExportForm,
  handleImport,
  handleSplit,
  handleMerge,
  handleDerive,
  handleExport,
} = useDatacenterExcel(
  selectedSourceId,
  selectedCatalogId,
  selectedTableId,
  reloadAll,
);

// 视图状态：empty | list | detail
const selectedNodeKey = ref('');
const viewMode = ref<'detail' | 'empty' | 'list'>('empty');

const isExcelContext = computed(() => {
  const st =
    selectedSource.value?.sourceType || schema.value?.source?.sourceType;
  return st === 'EXCEL' || st === 'EXCEL_MATERIALIZED';
});
const canImportExcel = computed(
  () => selectedSource.value?.sourceType === 'EXCEL',
);
const canExport = computed(() =>
  Boolean(selectedTable.value || selectedSource.value),
);
const canShowMoreActions = computed(
  () =>
    isExcelContext.value &&
    (Boolean(selectedTable.value) ||
      managedTables.value.length > 1 ||
      canExport.value),
);
const showToolbar = computed(
  () => canImportExcel.value || canShowMoreActions.value,
);
const { treeData, parseNodeKey } = useConnectionTree(sources);
const selectedFieldOptions = computed(() =>
  (schema.value?.fields || []).map((f: any) => ({
    label: f.fieldName,
    value: f.fieldName,
  })),
);

async function handleNodeSelect(node: TreeNode) {
  selectedNodeKey.value = node.id;

  switch (node.type) {
    case 'source': {
      const { id } = parseNodeKey(node.id);
      if (id !== selectedSourceId.value) {
        selectedSourceId.value = id;
        selectedCatalogId.value = null;
        selectedTableId.value = null;
        await syncSourceContext();
      }
      viewMode.value = 'list';

      break;
    }
    case 'table': {
      const { id } = parseNodeKey(node.id);
      selectedTableId.value = id;
      await loadTableRuntime();
      viewMode.value = 'detail';

      break;
    }
    // No default
  }
}

async function handleBatchRegister(rows: any[]) {
  await batchRegisterTables(rows);
}

async function handleBatchRemove(rows: any[]) {
  const removedIds = rows.map((row) => row?.id).filter(Boolean);
  await batchRemoveTables(rows);
  if (selectedTableId.value && removedIds.includes(selectedTableId.value)) {
    viewMode.value = 'list';
  }
}

async function handleSaveTableDescription(
  tableId: number | string,
  tableDesc: string,
) {
  await saveDescriptions({
    tableId,
    tableDesc,
    fields: [],
  });
}

function handleSelectTable(row: any) {
  selectedTableId.value = row.id;
  selectedNodeKey.value = `table-${row.id}`;
  viewMode.value = 'detail';
  loadTableRuntime();
}

function handleBackToList() {
  viewMode.value = 'list';
  if (selectedSource.value) {
    selectedNodeKey.value = `source-${selectedSource.value.id}`;
  }
}

function openCreate() {
  sourceFormRef.value?.open();
  sourceFormVisible.value = true;
}

function openEdit(node: TreeNode) {
  if (node.type !== 'source') return;
  sourceFormRef.value?.open(node.meta);
  sourceFormVisible.value = true;
}

async function handleRemoveSource(node: TreeNode) {
  if (node.type !== 'source' || !node.meta?.id) return;
  await ElMessageBox.confirm(`确认删除“${node.label}”吗？`, '删除连接', {
    type: 'warning',
    confirmButtonText: '删除',
    cancelButtonText: '取消',
    confirmButtonClass: 'el-button--danger',
  });
  const removingCurrent = selectedSourceId.value === node.meta.id;
  await removeSource(node.meta.id);
  if (removingCurrent) {
    selectedTableId.value = null;
  }
  await reloadAll({ focus: 'source', resetTable: true });
}

async function handleSaveSource(formData: Record<string, any>) {
  await saveSource(formData);
  sourceFormRef.value?.close();
  sourceFormVisible.value = false;
  await nextTick();
  await reloadAll({ focus: 'source', resetTable: true });
}

async function handleTestConnection(formData: Record<string, any>) {
  const result = await testConnection(formData);
  sourceFormRef.value?.setTestResult(result);
  if (formData.id) await loadSources();
}

function openExcelAction(
  action: 'derive' | 'export' | 'import' | 'merge' | 'split',
) {
  switch (action) {
    case 'derive': {
      resetDeriveForm();
      break;
    }
    case 'export': {
      resetExportForm();
      break;
    }
    case 'merge': {
      resetMergeForm();
      break;
    }
    case 'split': {
      resetSplitForm();
      break;
    }
  }
  excelActionRef.value?.open(action);
  excelActionVisible.value = true;
}

async function handleExcelAction(action: string) {
  let success = false;
  switch (action) {
    case 'derive': {
      success = await handleDerive();
      break;
    }
    case 'export': {
      success = await handleExport(loadTableRuntime);
      break;
    }
    case 'import': {
      success = await handleImport();
      break;
    }
    case 'merge': {
      success = await handleMerge();
      break;
    }
    case 'split': {
      success = await handleSplit();
      break;
    }
  }
  if (success) excelActionVisible.value = false;
}

async function loadAll() {
  loading.value = true;
  try {
    await reloadAll({ focus: 'source', resetTable: true });
  } finally {
    loading.value = false;
  }
}

function updateWorkspaceHeight() {
  const element = workspaceRef.value;
  if (!element) return;
  const top = element.getBoundingClientRect().top;
  workspaceHeight.value = `${Math.max(window.innerHeight - top, 480)}px`;
}

onMounted(async () => {
  await loadAll();
  await nextTick();
  updateWorkspaceHeight();
  window.addEventListener('resize', updateWorkspaceHeight);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', updateWorkspaceHeight);
});
</script>

<template>
  <div
    ref="workspaceRef"
    class="datacenter-workspace"
    :style="{ height: workspaceHeight }"
    v-loading="loading"
  >
    <!-- 顶部工具栏 -->
    <div v-if="showToolbar" class="workspace-toolbar">
      <div class="toolbar-left">
        <EasyFlowButton
          v-if="canImportExcel"
          class="toolbar-button"
          variant="outline"
          @click="openExcelAction('import')"
        >
          导入 Excel
        </EasyFlowButton>
        <ElDropdown v-if="canShowMoreActions">
          <EasyFlowButton class="toolbar-button" variant="outline">
            更多操作
          </EasyFlowButton>
          <template #dropdown>
            <ElDropdownMenu>
              <ElDropdownItem
                v-if="canExport"
                @click="openExcelAction('export')"
              >
                导出
              </ElDropdownItem>
              <ElDropdownItem
                v-if="selectedTable"
                @click="openExcelAction('split')"
              >
                拆分
              </ElDropdownItem>
              <ElDropdownItem
                v-if="managedTables.length > 1"
                @click="openExcelAction('merge')"
              >
                合并
              </ElDropdownItem>
              <ElDropdownItem
                v-if="selectedTable"
                @click="openExcelAction('derive')"
              >
                生成新表
              </ElDropdownItem>
            </ElDropdownMenu>
          </template>
        </ElDropdown>
      </div>
    </div>

    <!-- 双栏主体 -->
    <ResizablePanelGroup direction="horizontal" class="workspace-body">
      <ResizablePanel :default-size="20" :min-size="16" :max-size="30">
        <ConnectionTree
          :tree-data="treeData"
          :selected-key="selectedNodeKey"
          @create="openCreate"
          @edit="openEdit"
          @refresh="loadAll"
          @remove="handleRemoveSource"
          @select="handleNodeSelect"
        />
      </ResizablePanel>

      <ResizableHandle />

      <ResizablePanel :default-size="80" :min-size="44">
        <TableListView
          v-if="viewMode === 'list'"
          :source-tables="sourceTables"
          :managed-tables="managedTables"
          :save-table-description="handleSaveTableDescription"
          :source-label="selectedSource?.sourceName || ''"
          :source-unavailable="sourceUnavailable"
          @register-tables="handleBatchRegister"
          @remove-tables="handleBatchRemove"
          @select-table="handleSelectTable"
        />
        <TableDetailView
          v-else-if="viewMode === 'detail' && selectedTable"
          :table="selectedTable"
          :schema="schema"
          :preview-rows="previewRows"
          :jobs="jobs"
          :loading="previewLoading"
          :save-descriptions="saveDescriptions"
          :source-unavailable="sourceUnavailable"
          @back="handleBackToList"
        />
        <div v-else class="empty-state">
          <ElEmpty description="从左侧选择连接或表开始浏览" />
        </div>
      </ResizablePanel>
    </ResizablePanelGroup>

    <!-- Drawers -->
    <SourceFormDrawer
      ref="sourceFormRef"
      v-model:visible="sourceFormVisible"
      :saving="saving"
      :testing="testing"
      @save="handleSaveSource"
      @test="handleTestConnection"
    />

    <ExcelActionDrawer
      ref="excelActionRef"
      v-model:visible="excelActionVisible"
      v-model:split-form="splitForm"
      v-model:merge-form="mergeForm"
      v-model:derive-form="deriveForm"
      v-model:export-form="exportForm"
      :action-loading="actionLoading"
      :managed-tables="managedTables"
      :field-options="selectedFieldOptions"
      :pending-upload-file="pendingUploadFile"
      @update:pending-upload-file="(f) => (pendingUploadFile = f)"
      @import="handleExcelAction('import')"
      @split="handleExcelAction('split')"
      @merge="handleExcelAction('merge')"
      @derive="handleExcelAction('derive')"
      @export="handleExcelAction('export')"
    />
  </div>
</template>

<style scoped>
.datacenter-workspace {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 0;
  padding-top: 12px;
  margin-top: 0;
  overflow: hidden;
  background: transparent;
}

.workspace-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: flex-start;
  padding: 0 0 12px;
}

.toolbar-left {
  display: flex;
  gap: 8px;
  align-items: center;
}

.toolbar-button {
  min-width: 84px;
  box-shadow: none;
}

.workspace-body {
  flex: 1;
  width: 100%;
  min-height: 0;
  overflow: hidden;
  background: transparent;
}

.workspace-body :deep([data-panel-group-direction='horizontal']) {
  height: 100%;
}

.workspace-body :deep([data-panel-resize-handle-enabled]) {
  position: relative;
  width: 10px;
  background: transparent;
}

.workspace-body :deep([data-panel-resize-handle-enabled]::before) {
  position: absolute;
  top: 20px;
  bottom: 20px;
  left: 50%;
  width: 1px;
  content: '';
  background: hsl(var(--border) / 32%);
  transform: translateX(-50%);
}

.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  background: transparent;
}
</style>
