<script setup lang="ts">
import { object, string, type InferType } from 'yup'
import { apiBase } from '~/helpers';
import type { ApiTypeList, ApiTypeExternal } from '~/helpers';
import type { FormSubmitEvent } from '#ui/types'

const props = defineProps(['elements', 'partner'])
const route = useRoute()

const headers = new Headers();
headers.append("Content-Type", "application/json");

type ExternalDataType = {
    partner?: ApiTypeExternal[],
    categories?: ApiTypeExternal[][],
    element?: ApiTypeExternal[],
}
type StateDataType = {
    partner?: string
    categories?: string[]
    inventory?: string
    element?: string
    element_id?: string
}
const loading = ref(false)
const state = reactive<StateDataType>({
    partner: undefined,
    categories: [],
    inventory: route.params.inv_id as string || undefined,
    element: undefined,
    element_id: undefined
})
const external_data = reactive<ExternalDataType>({
    partner: [],
    categories: [],
    element: [],
})
const elements = ref(props.elements)
const schema = object({
    element: string().required('Required'),
    element_id: string().required('Required')
})
type Schema = InferType<typeof schema>

async function onSubmit(event: FormSubmitEvent<Schema>) {
    const prepader_data = event.data
    prepader_data.partner_name = external_data.partner.find(el => el.Ref_Key == state.partner)?.Description
    if(!prepader_data.partner_name) prepader_data.partner_name = prepader_data.partner

    const data = await $fetch(`${apiBase}/element/`, { method: 'POST', body: JSON.stringify(prepader_data) })
    const inv_id = route.params.inv_id || data.inventory?.id
    if (!route.params.inv_id) {
        navigateTo(`/organization/p_${data.partner.id}/i_${data.inventory.id}`)
    } else {
        const newElements = await $fetch<ApiTypeList>(`${apiBase}/element?inventory_id=${inv_id}`, { headers })
        elements.value = newElements.results
    }
}

const searchInExternal = (q: string) => {
    if (!q.length) {
        return external_data.partner?.splice(0, 10)
    }
    return external_data.partner?.filter(el => {
        return el.Description.toLowerCase().indexOf(q.toLowerCase()) !== -1
    }).slice(0, 10)
}

const loadPartners = async () => {
    loading.value = true
    const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/partner/external/`)
    if (data) {
        external_data.partner = data
        if (props.partner) {
            state.partner = props.partner
        }
    }
    loading.value = false
}
const loadCategories = async () => {
    loading.value = true

    const lastCat = state.categories?.at(-1) || ''
    const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/element/external_categories/${lastCat}`)
    if (data.length) {
        external_data.categories?.push(data)
    } else {
        await loadElements()
    }
    loading.value = false
}
const loadElements = async () => {
    loading.value = true

    const lastCat = state.categories?.at(-1) || ''
    const data = await $fetch<ApiTypeExternal[]>(`${apiBase}/element/external/${lastCat}`)
    if (data) {
        external_data.element = data
    }
    loading.value = false
}
const loadDeepCategories = async (i: number) => {
    if ((i + 1) <= (state.categories as string[]).length) {
        state.categories = state.categories?.slice(0, i + 1)
        external_data.categories = external_data.categories?.slice(0, i + 1)

        state.element = undefined
        external_data.element = []
    }

    loadCategories()
}
onMounted(async () => {
    await loadPartners()
    await loadCategories()
})
</script>
<template>
    <div class="grid grid-cols-10 gap-4">
        <div class="col-span-3">
            <UForm :state="state" class="flex flex-col gap-4" @submit="onSubmit">
                <UFormGroup label="Выбрать организацию" name="organization">
                    <USelectMenu v-model="state.partner" :options="external_data.partner" value-attribute="Ref_Key"
                        option-attribute="Description" :searchable="searchInExternal"
                        searchable-placeholder="Выберите организацию из списка контрагентов" :loading="loading"
                        :disabled="!!props.partner" />
                </UFormGroup>
                <UFormGroup label="Добавить элемент инвентаризации" v-if="state.partner">
                    <template v-for="(item, i) in external_data.categories">
                        <USelectMenu v-model="(state.categories as string[])[i]" :options="item"
                            value-attribute="Ref_Key" option-attribute="Description" :searchable="true"
                            :loading="loading" :placeholder="`Категории (${item.length})`"
                            @change="loadDeepCategories(i)" />
                    </template>
                    <USelectMenu v-if="external_data.element?.length" v-model="state.element"
                        :options="external_data.element" value-attribute="Ref_Key" option-attribute="Description"
                        :searchable="true" :loading="loading"
                        :placeholder="`Элементы (${external_data.element.length})`" />
                </UFormGroup>
                <UFormGroup v-if="state.element"
                    :label="`Данные об элементе «${external_data.element?.find(el => el['Ref_Key'] === state.element)?.Description}»`">
                    <UInput placeholder="ID" v-model="state.element_id" />
                </UFormGroup>

                <UButton type="submit" :disabled="!state.element_id">
                    Сохранить
                </UButton>
            </UForm>
        </div>
        <div class="col-span-7">
            <h2>{{ external_data.partner?.find(el => el["Ref_Key"] == state.partner)?.Description }}</h2>
            <dl v-if="elements?.length">
                <template v-for="item in elements">
                    <dt>
                        {{ item.external_id }}
                    </dt>
                    <dt>
                        {{ item.element_id }}
                    </dt>
                </template>
            </dl>
        </div>
    </div>
</template>
<style scoped>
label {
    word-wrap: break-word;
}
</style>