<script setup lang="ts">
import { apiBase } from '~/helpers';
import type { ApiTypeList, ApiTypeExternal, ApiElementSave } from '~/helpers';
import type { FormError, 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
    element_additional_data?: 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,
    element_additional_data: undefined
})
const external_data = reactive<ExternalDataType>({
    partner: [],
    categories: [],
    element: [],
})
const show_error = ref()

const elements = ref(props.elements)
const validate = (state: any): FormError[] => {
    const errors = []
    const txt = 'Это поле обязательно'
    if (!state.partner) errors.push({ path: 'partner', message: txt })
    if (!external_data || !external_data.partner || !external_data.partner.find(el => el.Ref_Key == state.partner)) {
        errors.push({ path: 'partner', message: txt })
    }
    if (!state.element_id) errors.push({ path: 'element_id', message: txt })
    // if (!state.element_additional_data) errors.push({ path: 'element_additional_data', message: txt })
    return errors
}

async function onSubmit(event: FormSubmitEvent<any>) {
    show_error.value = undefined
    const prepader_data = event.data
    if (!external_data || !external_data.partner) {
        return false
    }
    prepader_data.partner_name = external_data.partner.find(el => el.Ref_Key == state.partner)?.Description

    const data = await $fetch<ApiElementSave>(`${apiBase}/element/`, {
        method: 'POST', body: JSON.stringify(prepader_data), onResponseError: (error) => {
            if (error.response.status == 500) {
                show_error.value = Object.entries(error.response._data).map(el => `${el[0]}: ${el[1]}`).join('\n')
            }
        }
    })
    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
        external_data.element = []
        external_data.categories = []
        state.categories = []
        state.element = undefined
        state.element_id = undefined
        state.element_additional_data = undefined
    }
}

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" :validate="validate" class="flex flex-col gap-4" @submit="onSubmit">
                <UFormGroup label="Выбрать организацию" name="partner">
                    <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" :help="!external_data.element?.length ? `Последовательно 
                    выбирайте категорию. Если все выбрали, а элементов нет - 
                    значит в этой категории нет элементов`: ''">
                    <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>
                <div v-if="state.element">
                    <h4>Данные об элементе «{{ external_data.element?.find(el => el['Ref_Key'] ===
                        state.element)?.Description }}»</h4>
                    <UFormGroup label="ID" name="element_id">
                        <UInput placeholder="ID" v-model="state.element_id" />
                    </UFormGroup>
                    <UFormGroup label="Дополнительные сведения" name="element_additional_data">
                        <UTextarea placeholder="Дополнительные сведения" v-model="state.element_additional_data" />
                    </UFormGroup>
                </div>

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