<script lang="ts" setup generic="T extends {[key: string]: any}, P extends Path<T>">
import type {
	AttributeFn,
	AttributeValue,
	Attributes,
	BagelFieldOptions,
	BaseBagelField,
	BglFormSchemaT,
	Field,
	Path
} from '@bagelink/vue'
import type { MaybeRefOrGetter } from 'vue'
import { BagelForm, Btn, Loading, Icon } from '@bagelink/vue'
import { ref, computed, watch, toValue } from 'vue'

export interface FieldArrayProps<T, P extends Path<T>> {
	el?: any
	id: string
	label?: string
	placeholder?: string
	children?: Field<T>[]
	class?: AttributeValue | AttributeFn<T, P>
	attrs?: Attributes<T, P>
	required?: boolean
	disabled?: boolean
	helptext?: string
	options?: BagelFieldOptions<T, P>
	defaultValue?: any
	add?: boolean
	delete?: boolean
	transform?: (value: T) => T
	schema?: MaybeRefOrGetter<BglFormSchemaT<T>>
	modelValue: T[]
	type?: 'object' | 'number' | 'text'
}

export interface PrimitiveArrFieldT extends BaseBagelField<{ value: string }, 'value'> {
	type: FieldArrayProps<{ value: string }, 'value'>['type']
}

const props = withDefaults(
	defineProps<FieldArrayProps<T, P>>(),
	{
		delete: true,
		add: true,
		el: 'div',
		type: 'object',
	}
)

const emit = defineEmits(['update:modelValue'])

const BagelFormFA = BagelForm<T, P>

// State
const minimizedItems = ref<boolean[]>([])
const internalData = ref<any[]>(props.modelValue || [])
const schemaState = ref<'loading' | 'loaded' | 'error'>('loaded')

// Generate schema for primitive types
const primitiveSchema = computed<PrimitiveArrFieldT[]>(() => {
	if (props.type === 'text') {
		return [{ id: 'value', type: 'text', label: '', $el: 'text' }]
	} else if (props.type === 'number') {
		return [{ id: 'value', type: 'number', label: '', $el: 'number' }]
	}
	return []
})

const resolvedSchemaData = $computed(() => {
	if (props.type !== 'object') return primitiveSchema.value as BglFormSchemaT<T>

	return toValue(props.schema)
})

// Watch for external changes to modelValue
watch(() => props.modelValue, (newValue) => {
	internalData.value = newValue || []
}, { deep: true })

// Resolve schema
// async function resolveSchema() {
// 	// For primitive types, use the predefined schemaks
// 	if (props.type !== 'object') {
// 		resolvedSchemaData.value = primitiveSchema.value
// 		schemaState.value = 'loaded'
// 		return
// 	}

// 	// For object type without schema
// 	if (!props.schema) {
// 		resolvedSchemaData.value = []
// 		schemaState.value = 'loaded'
// 		return
// 	}

// 	// For object type with schema
// 	try {
// 		// schemaState.value = 'loading'
// 		const isPromise = (obj: any) => obj && typeof obj.then === 'function'

// 		let result: any
// 		if (typeof props.schema === 'function') {
// 			result = props.schema()
// 			result = isPromise(result) ? await result : result
// 		} else {
// 			result = isPromise(props.schema) ? await props.schema : props.schema
// 		}

// 		resolvedSchemaData.value = result
// 		schemaState.value = 'loaded'
// 	} catch (error) {
// 		console.error('Schema error:', error)
// 		schemaState.value = 'error'
// 		resolvedSchemaData.value = []
// 	}
// }

// // Initialize schema on mount
// onMounted(resolveSchema)

// Event handlers
function emitValue() {
	emit('update:modelValue', internalData.value)
}

function deleteItem(i: number) {
	internalData.value.splice(i, 1)
	emitValue()
}

function addItem() {
	// Add appropriate default value based on type
	const defaultValues = {
		text: '',
		number: 0,
		object: {}
	}
	internalData.value.push(defaultValues[props.type])
	emitValue()
}

function toggleMinimized(index: number) {
	minimizedItems.value[index] = !minimizedItems.value[index]
}

function updateItem(index: number, value: any) {
	// Handle primitive types by extracting the value property
	if (props.type === 'text' || props.type === 'number') {
		internalData.value[index] = props.type === 'number' ? Number(value.value) : value.value
	} else {
		internalData.value[index] = value
	}
	emitValue()
}

// Computed properties for rendering
const isPrimitiveType = computed(() => props.type === 'text' || props.type === 'number')
const canRenderItems = computed(
	() => isPrimitiveType.value || (
		props.type === 'object' && Number(resolvedSchemaData?.length) > 0
	)
)
const showMinimizeButton = computed(() => {
	return Number(resolvedSchemaData?.length) > 2 || resolvedSchemaData?.some(schema => schema.$el === 'richtext')
})
</script>

<template>
	<div :class="props.class">
		<!-- Label -->
		<p v-if="label" class="label mb-05">
			{{ label }}
		</p>
		<div class="ps-025 border-start mb-05">
			<!-- Loading/Error States -->
			<div v-if="schemaState !== 'loaded'" class="flex-center h-300px">
				<Loading v-if="schemaState === 'loading'" />
				<Icon v-else-if="schemaState === 'error'" icon="error" color="red" />
			</div>

			<!-- No Schema Available -->
			<div v-else-if="!canRenderItems" class="py-1">
				<p class="opacity-7">
					No schema available
				</p>
			</div>

			<!-- Items Rendering -->
			<template v-else>
				<!-- Array Items -->
				<div
					v-for="(item, i) in internalData"
					:key="i"
					outline
					thin
					class="mb-05 itemBox transition ps-05 pb-025 pt-025 radius-05 gap-05 overflow-hidden"
					:class="{ minimized: minimizedItems[i] }"
				>
					<!-- Minimized View -->
					<p v-if="minimizedItems[i]" class="minimizedText txt14 p-025 opacity-7">
						{{ label }} {{ i + 1 }}
					</p>

					<!-- Form View -->
					<BagelFormFA
						v-else
						:model-value="isPrimitiveType ? { value: item } : item"
						:schema="resolvedSchemaData"
						@update:model-value="val => updateItem(i, val)"
					/>

					<!-- Controls -->
					<div class="bg-gray-80 -my-05 px-025 pt-065 pb-05 txt-center space-between flex column">
						<Btn
							v-if="showMinimizeButton"
							class="block rotate-180 txt10 opacity-7 p-025"
							flat
							thin
							icon="keyboard_arrow_down"
							@click="toggleMinimized(i)"
						/>
						<Btn
							v-if="props.delete"
							icon="delete"
							class="txt10 opacity-7"
							thin
							flat
							@click="deleteItem(i)"
						/>
					</div>
				</div>

				<!-- Add Button -->
				<Btn v-if="add" thin icon="add" color="gray" class="txt12  arrayAddButton" @click="addItem">
					<p>{{ label }}</p>
				</Btn>
			</template>
		</div>
	</div>
</template>

<style>
.minimized {
	height: 2.4rem;
	overflow: hidden;
}
.minimizedText {
	display: none;
}
.minimized .minimizedText {
	display: block;
}
.minimized .rotate-180 {
	transform: rotate(0deg);
}
.itemBox {
	background: var(--input-bg);
	grid-template-columns: 1fr auto;
	display: grid;
	--label-font-size: 0.6rem;
	--input-height: 30px;
	--input-font-size: 14px;
}

.pt-065 {
	padding-top: 0.65rem;
}

.itemBox .bagel-input input,
.itemBox .bagel-input textarea,
.itemBox .bagel-input select,
.itemBox .custom-select .input {
	background: var(--bgl-white) !important;
}
.itemBox .code-editor-wrap textarea {
	background: transparent !important;
}
.itemBox .bagel-input {
	margin-bottom: 0.15rem !important;
}
</style>
