import type { Ref } from 'vue';

import { computed, ref } from 'vue';

import { ElMessage } from 'element-plus';

import { requestClient } from '#/api/request';

interface DatacenterTableRuntimeOptions {
  clearSourceRuntimeUnavailable?: (sourceId?: null | number | string) => void;
  markSourceRuntimeUnavailable?: (sourceId?: null | number | string) => void;
}

export function useDatacenterTables(
  selectedSourceId: Ref<null | number>,
  options: DatacenterTableRuntimeOptions = {},
) {
  const SOURCE_MISSING_MESSAGE = '连接不存在';
  const SOURCE_UNAVAILABLE_MESSAGE = '当前连接不可用，请检查连接配置后重试';
  const catalogs = ref<any[]>([]);
  const sourceTables = ref<any[]>([]);
  const managedTables = ref<any[]>([]);
  const schema = ref<any>(null);
  const previewRows = ref<any[]>([]);
  const jobs = ref<any[]>([]);
  const sourceUnavailable = ref(false);
  const selectedCatalogId = ref<null | number>(null);
  const selectedTableId = ref<null | number>(null);
  const previewLoading = ref(false);

  const selectedCatalog = computed(
    () =>
      catalogs.value.find((item) => item.id === selectedCatalogId.value) ||
      null,
  );

  const selectedTable = computed(
    () =>
      managedTables.value.find((item) => item.id === selectedTableId.value) ||
      null,
  );

  function isSourceUnavailableError(error: any) {
    const responseData = error?.response?.data ?? {};
    const message = String(responseData?.message ?? error?.message ?? '');
    return message.includes(SOURCE_UNAVAILABLE_MESSAGE);
  }

  function isSourceMissingError(error: any) {
    const responseData = error?.response?.data ?? {};
    const message = String(responseData?.message ?? error?.message ?? '');
    return message.includes(SOURCE_MISSING_MESSAGE);
  }

  function markSourceUnavailable() {
    options.markSourceRuntimeUnavailable?.(selectedSourceId.value);
    catalogs.value = [];
    sourceTables.value = [];
    managedTables.value = [];
    schema.value = null;
    previewRows.value = [];
    jobs.value = [];
    selectedCatalogId.value = null;
    selectedTableId.value = null;
    sourceUnavailable.value = true;
  }

  async function loadCatalogs() {
    if (!selectedSourceId.value) {
      catalogs.value = [];
      selectedCatalogId.value = null;
      sourceUnavailable.value = false;
      return true;
    }
    try {
      const data = await requestClient.get(
        '/api/v1/datacenterSource/catalogs',
        {
          params: { sourceId: selectedSourceId.value },
        },
      );
      options.clearSourceRuntimeUnavailable?.(selectedSourceId.value);
      catalogs.value = data || [];
      sourceUnavailable.value = false;
      if (catalogs.value.length === 0) {
        selectedCatalogId.value = null;
        return true;
      }
      if (
        !selectedCatalogId.value ||
        !catalogs.value.some((item) => item.id === selectedCatalogId.value)
      ) {
        selectedCatalogId.value = catalogs.value[0].id;
      }
      return true;
    } catch (error) {
      if (isSourceMissingError(error)) {
        markSourceUnavailable();
        return false;
      }
      if (!isSourceUnavailableError(error)) {
        throw error;
      }
      markSourceUnavailable();
      return false;
    }
  }

  async function loadSourceTables() {
    if (!selectedSourceId.value) {
      sourceTables.value = [];
      return;
    }
    try {
      const data = await requestClient.get('/api/v1/datacenterSource/tables', {
        params: {
          sourceId: selectedSourceId.value,
          catalogName: selectedCatalog.value?.catalogName,
        },
      });
      options.clearSourceRuntimeUnavailable?.(selectedSourceId.value);
      sourceTables.value = data || [];
      sourceUnavailable.value = false;
    } catch (error) {
      if (!isSourceUnavailableError(error) && !isSourceMissingError(error)) {
        throw error;
      }
      markSourceUnavailable();
    }
  }

  async function loadManagedTables() {
    if (!selectedSourceId.value) {
      managedTables.value = [];
      selectedTableId.value = null;
      return;
    }
    try {
      const data = await requestClient.get(
        '/api/v1/datacenterDataset/managedTables',
        {
          params: {
            sourceId: selectedSourceId.value,
            catalogId: selectedCatalogId.value,
          },
        },
      );
      managedTables.value = data || [];
    } catch (error) {
      if (!isSourceUnavailableError(error) && !isSourceMissingError(error)) {
        throw error;
      }
      markSourceUnavailable();
      return;
    }
    if (managedTables.value.length === 0) {
      selectedTableId.value = null;
      return;
    }
    if (
      !selectedTableId.value ||
      !managedTables.value.some((item) => item.id === selectedTableId.value)
    ) {
      selectedTableId.value = managedTables.value[0].id;
    }
  }

  async function loadTableRuntime() {
    if (!selectedTableId.value) {
      schema.value = null;
      previewRows.value = [];
      jobs.value = [];
      return;
    }
    previewLoading.value = true;
    try {
      const [schemaRes, previewRes, jobsRes] = await Promise.allSettled([
        requestClient.get('/api/v1/datacenterDataset/schema', {
          params: { tableId: selectedTableId.value },
        }),
        requestClient.post('/api/v1/datacenterDataset/queryPage', {
          datasetRef: { tableId: selectedTableId.value },
          pageNumber: 1,
          pageSize: 10,
        }),
        requestClient.get('/api/v1/datacenterExcel/job/list', {
          params: {
            sourceId: selectedSourceId.value,
            tableId: selectedTableId.value,
          },
        }),
      ]);
      if (schemaRes.status === 'fulfilled') {
        schema.value = schemaRes.value;
      } else if (
        isSourceUnavailableError(schemaRes.reason) ||
        isSourceMissingError(schemaRes.reason)
      ) {
        markSourceUnavailable();
        return;
      } else {
        throw schemaRes.reason;
      }
      if (jobsRes.status === 'fulfilled') {
        jobs.value = jobsRes.value || [];
      } else if (
        isSourceUnavailableError(jobsRes.reason) ||
        isSourceMissingError(jobsRes.reason)
      ) {
        markSourceUnavailable();
        return;
      } else {
        throw jobsRes.reason;
      }
      if (previewRes.status === 'fulfilled') {
        options.clearSourceRuntimeUnavailable?.(selectedSourceId.value);
        previewRows.value = previewRes.value?.records || [];
        sourceUnavailable.value = false;
      } else if (
        isSourceUnavailableError(previewRes.reason) ||
        isSourceMissingError(previewRes.reason)
      ) {
        markSourceUnavailable();
      } else {
        throw previewRes.reason;
      }
    } finally {
      previewLoading.value = false;
    }
  }

  async function syncSourceContext() {
    const catalogAvailable = await loadCatalogs();
    if (catalogAvailable) {
      await Promise.all([loadSourceTables(), loadManagedTables()]);
    } else {
      sourceTables.value = [];
      await loadManagedTables();
    }
    await loadTableRuntime();
  }

  async function registerTable(row: any) {
    const data = await requestClient.get(
      '/api/v1/datacenterSource/tableDetail',
      {
        params: {
          sourceId: selectedSourceId.value,
          catalogName: selectedCatalog.value?.catalogName,
          tableName: row.tableName,
          register: true,
        },
      },
    );
    ElMessage.success('已接入数据中心');
    await loadManagedTables();
    selectedTableId.value = data?.table?.id || selectedTableId.value;
    await loadTableRuntime();
  }

  async function batchRegisterTables(rows: any[]) {
    const tableNames = (rows || [])
      .map((row) => row?.tableName)
      .filter(Boolean);
    if (tableNames.length === 0) return;
    await requestClient.post('/api/v1/datacenterSource/registerBatch', {
      sourceId: selectedSourceId.value,
      catalogName: selectedCatalog.value?.catalogName,
      tableNames,
    });
    ElMessage.success(`已接入 ${tableNames.length} 张表`);
    await loadManagedTables();
  }

  async function batchRemoveTables(rows: any[]) {
    const tableIds = (rows || []).map((row) => row?.id).filter(Boolean);
    if (tableIds.length === 0) return;
    await requestClient.post('/api/v1/datacenterDataset/removeBatch', {
      tableIds,
    });
    ElMessage.success(`已去除 ${tableIds.length} 张表`);
    if (selectedTableId.value && tableIds.includes(selectedTableId.value)) {
      selectedTableId.value = null;
      schema.value = null;
      previewRows.value = [];
      jobs.value = [];
    }
    await Promise.all([loadSourceTables(), loadManagedTables()]);
  }

  async function saveDescriptions(payload: {
    fields?: Array<{ fieldDesc: string; fieldId: number | string }>;
    tableDesc?: string;
    tableId: number | string;
  }) {
    const data = await requestClient.post(
      '/api/v1/datacenterDataset/saveDescriptions',
      {
        fields: payload.fields || [],
        tableDesc: payload.tableDesc ?? '',
        tableId: payload.tableId,
      },
    );
    await loadManagedTables();
    if (selectedTableId.value === payload.tableId) {
      schema.value = data || null;
    }
    return data;
  }

  return {
    catalogs,
    sourceTables,
    managedTables,
    schema,
    previewRows,
    jobs,
    sourceUnavailable,
    selectedCatalogId,
    selectedTableId,
    selectedCatalog,
    selectedTable,
    previewLoading,
    loadCatalogs,
    loadSourceTables,
    loadManagedTables,
    loadTableRuntime,
    syncSourceContext,
    registerTable,
    batchRegisterTables,
    batchRemoveTables,
    saveDescriptions,
  };
}
