<template>
	<el-scrollbar class="w-full box-border p-12px">
		<div class="database-setter">
			<section class="section-block">
				<div class="section-title">{{ texts.connection }}</div>

				<el-form label-position="top">
					<el-form-item :label="texts.dbType">
						<el-select
							v-model="formData.db_type"
							class="w-full"
							:placeholder="texts.dbTypePlaceholder"
							@change="handleDbTypeChange"
						>
							<el-option
								v-for="item in dbTypeOptions"
								:key="item.value"
								:label="item.label"
								:value="item.value"
							/>
						</el-select>
					</el-form-item>

					<div class="grid-row">
						<el-form-item :label="texts.dbHost" class="grid-col">
							<VarInput
								v-model="formData.db_host"
								:placeholder="texts.dbHostPlaceholder"
								class="w-full"
							/>
						</el-form-item>
						<el-form-item :label="texts.dbPort" class="grid-col grid-col--sm">
							<el-input-number
								v-model="formData.db_port"
								class="w-full"
								:min="1"
								:max="65535"
								:placeholder="texts.dbPortPlaceholder"
								style="width: 100%"
							/>
						</el-form-item>
					</div>

					<div class="grid-row">
						<el-form-item :label="texts.dbUsername" class="grid-col">
							<VarInput
								v-model="formData.db_username"
								:placeholder="texts.dbUsernamePlaceholder"
								class="w-full"
							/>
						</el-form-item>
						<el-form-item :label="texts.dbName" class="grid-col">
							<VarInput
								v-model="formData.db_name"
								:placeholder="texts.dbNamePlaceholder"
								class="w-full"
							/>
						</el-form-item>
					</div>

					<el-form-item
						:label="texts.password"
						tip="例如：alt_host=host1&alt_host=host2&ssl_cipher=%2Fpath%2Fto%2Fcrt"
					>
						<SecretInput v-model="formData.db_password" class="w-full" />
					</el-form-item>

					<el-form-item :label="texts.dbProperties">
						<VarInput
							v-model="formData.db_properties"
							:placeholder="texts.dbPropertiesPlaceholder"
							class="w-full var-input-textarea var-input-textarea--lg"
						/>
					</el-form-item>
				</el-form>
			</section>

			<section class="section-block">
				<div class="section-title">{{ texts.query }}</div>
				<el-form label-position="top">
					<el-form-item :label="texts.querySql">
						<VarInput
							v-model="formData.query_sql"
							:placeholder="texts.querySqlPlaceholder"
							class="w-full var-input-textarea var-input-textarea--xl"
						/>
					</el-form-item>
				</el-form>
			</section>

			<section class="section-block">
				<ErrorHandling
					v-model:error_strategy="formData.error_strategy"
					v-model:default_value="formData.default_value"
					:outputs="formData.outputs"
				/>
			</section>

			<section class="section-block">
				<RetryConfig v-model="formData.retry_config" />
			</section>
		</div>
	</el-scrollbar>
</template>

<script setup lang="ts">
import { computed, watch } from 'vue'

import ErrorHandling from '@/nodes/_base/ErrorHandling.vue'
import RetryConfig from '@/nodes/_base/RetryConfig.vue'
import VarInput from '@/nodes/_base/VarInput.vue'
import SecretInput from '@/features/secretInput/SecretInput.vue'
import { useI18n } from '@/composables/useI18n'
import { useSetterModel } from '../_shared/useSetterModel'

import type { DatabaseData, DatabaseType } from './index'

interface Emits {
	(e: 'update', value: DatabaseData): void
}

const props = defineProps<{
	data: DatabaseData
}>()

const emit = defineEmits<Emits>()
const { t } = useI18n()
const formData = useSetterModel<DatabaseData>(props, emit)

const texts = computed(() => ({
	connection: t('pages.databaseSetter.connection'),
	query: t('pages.databaseSetter.query'),
	dbType: t('pages.databaseSetter.dbType'),
	dbTypePlaceholder: t('pages.databaseSetter.dbTypePlaceholder'),
	dbHost: t('pages.databaseSetter.dbHost'),
	dbHostPlaceholder: t('pages.databaseSetter.dbHostPlaceholder'),
	dbPort: t('pages.databaseSetter.dbPort'),
	dbPortPlaceholder: t('pages.databaseSetter.dbPortPlaceholder'),
	dbUsername: t('pages.databaseSetter.dbUsername'),
	dbUsernamePlaceholder: t('pages.databaseSetter.dbUsernamePlaceholder'),
	dbName: t('pages.databaseSetter.dbName'),
	dbNamePlaceholder: t('pages.databaseSetter.dbNamePlaceholder'),
	dbProperties: t('pages.databaseSetter.dbProperties'),
	dbPropertiesPlaceholder: t('pages.databaseSetter.dbPropertiesPlaceholder'),
	querySql: t('pages.databaseSetter.querySql'),
	querySqlPlaceholder: t('pages.databaseSetter.querySqlPlaceholder'),
	mysql: t('pages.databaseSetter.types.mysql'),
	sqlserver: t('pages.databaseSetter.types.sqlserver'),
	oracle: t('pages.databaseSetter.types.oracle'),
	postgresql: t('pages.databaseSetter.types.postgresql'),
	password: '密码'
}))

const dbTypeOptions = computed<Array<{ label: string; value: DatabaseType }>>(() => [
	{ label: texts.value.mysql, value: 'mysql' },
	{ label: texts.value.sqlserver, value: 'sqlserver' },
	{ label: texts.value.oracle, value: 'oracle' },
	{ label: texts.value.postgresql, value: 'postgresql' }
])

const DEFAULT_PORT_MAP: Record<DatabaseType, number> = {
	mysql: 3306,
	sqlserver: 1433,
	oracle: 1521,
	postgresql: 5432
}

const ensureDefaults = () => {
	formData.value.title ||= t('nodes.meta.database.displayName')
	formData.value.type ||= 'database'
	formData.value.isInIteration ??= false
	formData.value.iteration_id ||= ''
	formData.value.isInLoop ??= false
	formData.value.loop_id ||= ''
	formData.value.variables ||= []
	formData.value.retry_config ||= {
		retry_enabled: false,
		max_retries: 3,
		retry_interval: 100
	}
	formData.value.error_strategy ||= 'none'
	formData.value.fail_branch_node_id ||= ''
	formData.value.default_value ||= []
	formData.value.output_can_alter ??= false
	formData.value.outputs ||= [
		{ name: 'rows', describe: t('nodes.outputs.database.rows'), type: 'array[object]' },
		{ name: 'row_count', describe: t('nodes.outputs.database.rowCount'), type: 'number' }
	]
	formData.value.db_type ||= 'mysql'
	formData.value.db_host ||= ''
	formData.value.db_port ||= DEFAULT_PORT_MAP[formData.value.db_type]
	formData.value.db_username ||= ''
	formData.value.db_name ||= ''
	formData.value.db_properties ||= ''
	formData.value.query_sql ||= ''
}

watch(
	formData,
	() => {
		ensureDefaults()
	},
	{ deep: true, immediate: true }
)

const handleDbTypeChange = (value: DatabaseType) => {
	if (!formData.value.db_port || Object.values(DEFAULT_PORT_MAP).includes(formData.value.db_port)) {
		formData.value.db_port = DEFAULT_PORT_MAP[value]
	}
}
</script>

<style scoped lang="less">
.database-setter {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.section-block {
	padding-bottom: 16px;
	border-bottom: 1px solid #eeeeee;
}

.section-title {
	margin-bottom: 12px;
	font-size: 14px;
	font-weight: 700;
	color: #374151;
}

.grid-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 12px;
}

.grid-col {
	min-width: 0;
}

.grid-col--sm {
	max-width: 180px;
}

.var-input-textarea {
	:deep(.el-input__wrapper) {
		align-items: flex-start;
		padding-top: 6px;
		padding-bottom: 6px;
	}

	:deep(.el-input__inner) {
		min-height: 72px;

		p {
			line-height: 24px;
		}
	}
}

.var-input-textarea--md {
	:deep(.el-input__inner) {
		min-height: 72px;
	}
}

.var-input-textarea--lg {
	:deep(.el-input__inner) {
		min-height: 96px;
	}
}

.var-input-textarea--xl {
	:deep(.el-input__inner) {
		min-height: 220px;
	}
}
</style>
