import type { FormRules } from 'element-plus';

import { computed, reactive, ref, watch } from 'vue';

import {
  mergeConfigJsonBySourceType,
  sourceConnectionDefaults,
  sourceTypeLabels,
} from './datacenter-constants';

export function useSourceForm() {
  const lastGeneratedJdbcUrl = ref('');
  const lastGeneratedDriverClassName = ref('');

  const form = reactive<Record<string, any>>({
    id: undefined,
    sourceName: '',
    sourceCode: '',
    sourceType: 'MYSQL',
    accessMode: 'READ_ONLY',
    driverClassName: '',
    jdbcUrl: '',
    host: '',
    port: undefined,
    databaseName: '',
    schemaName: '',
    username: '',
    password: '',
    builtinFlag: 0,
    configJson: {},
  });

  const rules: FormRules = {
    sourceName: [
      { required: true, message: '请输入连接名称', trigger: 'blur' },
    ],
    sourceType: [
      { required: true, message: '请选择连接类型', trigger: 'change' },
    ],
    databaseName: [
      {
        trigger: ['blur', 'change'],
        validator: (_rule, value, callback) => {
          if (!sourceConnectionDefaults[form.sourceType]) {
            callback();
            return;
          }
          if (String(value || '').trim()) {
            callback();
            return;
          }
          callback(new Error('请输入库名'));
        },
      },
    ],
  };

  const selectedTypeDefaults = computed(
    () => sourceConnectionDefaults[form.sourceType] || null,
  );

  const supportsExternalConnection = computed(() =>
    Boolean(selectedTypeDefaults.value),
  );

  const connectionTypeLabel = computed(() =>
    form.sourceType ? sourceTypeLabels[form.sourceType] || form.sourceType : '',
  );

  const connectionHelpText = computed(() => {
    if (form.sourceType === 'EXCEL') {
      return 'Excel 连接只需要名称，文件导入后会自动生成表。';
    }
    if (!supportsExternalConnection.value) {
      return '系统内置连接由平台自动维护，无需填写地址。';
    }
    return `填写主机、库名和账号即可，端口与连接地址会按 ${connectionTypeLabel.value} 自动补全。`;
  });

  function generateJdbcUrl(payload: Record<string, any>) {
    return (
      sourceConnectionDefaults[payload.sourceType]?.buildJdbcUrl(payload) || ''
    );
  }

  function syncGeneratedJdbcUrl(force = false) {
    const generated = generateJdbcUrl(form);
    if (!generated) {
      if (
        force ||
        !form.jdbcUrl ||
        form.jdbcUrl === lastGeneratedJdbcUrl.value
      ) {
        form.jdbcUrl = '';
      }
      lastGeneratedJdbcUrl.value = '';
      return;
    }
    if (force || !form.jdbcUrl || form.jdbcUrl === lastGeneratedJdbcUrl.value) {
      form.jdbcUrl = generated;
      lastGeneratedJdbcUrl.value = generated;
    } else if (form.jdbcUrl === generated) {
      lastGeneratedJdbcUrl.value = generated;
    }
  }

  function applySourceTypeDefaults(force = false) {
    const defaults = selectedTypeDefaults.value;
    form.configJson = mergeConfigJsonBySourceType(
      form.sourceType,
      form.configJson,
    );
    if (!defaults) {
      if (force) {
        form.port = undefined;
        form.driverClassName = '';
        form.jdbcUrl = '';
        lastGeneratedDriverClassName.value = '';
        lastGeneratedJdbcUrl.value = '';
      }
      return;
    }
    if (force || !form.port) {
      form.port = defaults.defaultPort;
    }
    if (
      force ||
      !form.driverClassName ||
      form.driverClassName === lastGeneratedDriverClassName.value
    ) {
      form.driverClassName = defaults.defaultDriver;
      lastGeneratedDriverClassName.value = defaults.defaultDriver;
    }
    syncGeneratedJdbcUrl(force);
  }

  function resetForm(row?: any) {
    form.id = row?.id;
    form.sourceName = row?.sourceName || '';
    form.sourceCode = row?.sourceCode || '';
    form.sourceType = row?.sourceType || 'MYSQL';
    form.accessMode = row?.accessMode || 'READ_ONLY';
    form.driverClassName = row?.driverClassName || '';
    form.jdbcUrl = row?.jdbcUrl || '';
    form.host = row?.host || '';
    form.port = row?.port;
    form.databaseName = row?.databaseName || '';
    form.schemaName = row?.schemaName || '';
    form.username = row?.username || '';
    form.password = '';
    form.builtinFlag = row?.builtinFlag || 0;
    form.configJson = mergeConfigJsonBySourceType(
      form.sourceType,
      row?.configJson || {},
    );
    lastGeneratedDriverClassName.value = '';
    lastGeneratedJdbcUrl.value = '';
    applySourceTypeDefaults(false);
  }

  watch(
    () => form.sourceType,
    () => applySourceTypeDefaults(true),
  );

  watch(
    () => [
      form.host,
      form.port,
      form.databaseName,
      form.configJson?.informixServer,
      form.configJson?.serviceName,
    ],
    () => syncGeneratedJdbcUrl(false),
  );

  return {
    form,
    rules,
    supportsExternalConnection,
    connectionHelpText,
    resetForm,
  };
}
