<script setup lang="ts">
import type { ModeType } from '../../../utils/calendar/typings'
import { TextInput, Dropdown, fmtDate } from '@bagelink/vue'
import { onClickOutside } from '@vueuse/core'
import { ref, onMounted } from 'vue'
import { WEEK_START_DAY } from '../../../utils/calendar/time'
import DatePicker from './DatePicker.vue'

const props = withDefaults(
	defineProps<{
		required?: boolean
		label?: string
		editMode?: boolean
		small?: boolean
		/**
		 * Whether to enable time selection.
		 * @default false
		 */
		enableTime?: boolean
		modelValue?: string | Date
		min?: string | Date
		max?: string | Date
		mode?: ModeType
		defaultValue?: string | Date
		firstDayOfWeek?: WEEK_START_DAY
		locale?: string
		center?: boolean
	}>(),
	{
		enableTime: false,
		editMode: true,
		small: false,
		mode: () => ({ mode: 'day' }),
		firstDayOfWeek: WEEK_START_DAY.SUNDAY,
		locale: ''
	},
)

const selectedDate = defineModel<string | Date>({
	required: true,
	default: () => new Date()
})

const isOpen = ref(false)

// Date formatting composable
function useFormatting() {
	const formatDisplayDate = (date: Date | string | undefined): string => {
		if (!date) return ''
		return fmtDate(date, { fmt: props.enableTime ? 'DD.MM.YY HH:mm' : 'DD.MM.YY' })
	}

	const parseUserInput = (input: string): Date | null => {
		// Try parsing various date formats
		const date = new Date(input)
		if (!Number.isNaN(date.getTime())) {
			return date
		}

		// Try DD/MM/YYYY format
		const parts = input.split(/[/.-]/)
		if (parts.length === 3) {
			const [day, month, year] = parts.map(p => Number.parseInt(p, 10))
			if (!Number.isNaN(day) && !Number.isNaN(month) && !Number.isNaN(year)) {
				const date = new Date(year, month - 1, day)
				if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {
					return date
				}
			}
		}

		return null
	}

	return {
		formatDisplayDate,
		parseUserInput
	}
}

// Initialize formatting
const { formatDisplayDate, parseUserInput } = useFormatting()

// Input handling composable
function useInputHandling() {
	const inputValue = ref('')

	const handleInput = (event: Event) => {
		const input = event.target as HTMLInputElement
		inputValue.value = input.value

		const date = parseUserInput(input.value)
		if (date) {
			selectedDate.value = date.toISOString()
		}
	}

	const handleFocus = (e: FocusEvent) => {
		e.preventDefault()
		e.stopPropagation()
		isOpen.value = true
	}

	const handleClick = (e: MouseEvent) => {
		e.preventDefault()
		e.stopPropagation()
	}

	const handleKeydown = (event: KeyboardEvent) => {
		if (event.key === 'Escape') {
			isOpen.value = false
		} else if (event.key === 'Enter' && inputValue.value) {
			const date = parseUserInput(inputValue.value)
			if (date) {
				selectedDate.value = date.toISOString()
				isOpen.value = false
			}
		}
	}

	return {
		inputValue,
		handleInput,
		handleFocus,
		handleClick,
		handleKeydown
	}
}

// Initialize input handling
const {
	handleInput,
	handleFocus,
	handleClick,
	handleKeydown
} = useInputHandling()

const datePickerRef = ref<HTMLElement | null>(null)
const calendarRef = ref<HTMLElement | null>(null)

onMounted(() => {
	onClickOutside(datePickerRef.value, () => {
		isOpen.value = false
	}, {
		ignore: () => [calendarRef.value]
	})
})
</script>

<template>
	<div class="bagel-input" :class="{ small }" :title="label" @focusin="handleFocus">
		<label v-if="label">
			{{ label }}
			<span v-if="required" class="required">*</span>
		</label>
		<Dropdown
			:shown="isOpen"
			placement="bottom-start"
			:autoHide="false"
			:triggers="['click']"
		>
			<template #trigger>
				<div ref="datePickerRef" class="date-picker-container" @mousedown.stop @click.stop>
					<TextInput
						:modelValue="formatDisplayDate(selectedDate)"
						iconStart="calendar"
						:min="formatDisplayDate(min)"
						:max="formatDisplayDate(max)"
						:required="required"
						:disabled="!editMode"
						class="date-input m-0"
						:class="{
							'txt-center': center,
						}"
						:readonly="false"
						@input="handleInput"
						@focus="handleFocus"
						@click="handleClick"
						@keydown="handleKeydown"
					/>
				</div>
			</template>

			<div ref="calendarRef" @click.stop>
				<DatePicker
					v-model="selectedDate"
					:min="min"
					:max="max"
					:mode="mode"
					:firstDayOfWeek="firstDayOfWeek"
					:locale="locale"
					:enableTime="enableTime"
				/>
			</div>
		</Dropdown>
	</div>
</template>

<style>
.date-picker-container {
	width: 100%;
}
</style>
