<template>
    <v-container>
        <v-row >
            <v-col>

                <v-stepper v-model="stepper" >
                    <template v-slot:default="{ prev, next }">
                        <v-stepper-header>
                            <v-stepper-item :title="$t('Import')" value="1"></v-stepper-item>
                            <v-divider></v-divider>
                            <v-stepper-item :title="$t('Image')" value="2"></v-stepper-item>
                            <v-divider></v-divider>
                            <v-stepper-item :title="$t('Keywords')" value="3"></v-stepper-item>
                            <v-divider></v-divider>
                            <v-stepper-item :title="$t('Steps')" value="4"></v-stepper-item>
                            <v-divider></v-divider>
                            <v-stepper-item :title="$t('Save')" value="5"></v-stepper-item>
                        </v-stepper-header>

                        <v-stepper-window>
                            <v-stepper-window-item value="1" >
                                <v-card :loading="loading">
                                    <v-card-text>
                                        <v-text-field :label="$t('Website') + ' (https://...)'" v-model="importUrl">
                                            <template #append>
                                                <v-btn color="primary" icon="fa-solid fa-cloud-arrow-down fa-fw" @click="loadRecipeFromUrl()"></v-btn>
                                            </template>
                                        </v-text-field>

                                        <v-file-input v-model="image" :label="$t('Image')" @click="uploadAndConvertImage()">
                                            <template #append>
                                                <v-btn>AI Import</v-btn>
                                            </template>
                                        </v-file-input>

                                        <!-- <v-textarea :placeholder="$t('paste_json')"></v-textarea> -->

                                        <v-alert variant="tonal" v-if="importResponse.duplicates && importResponse.duplicates.length > 0">
                                            <v-alert-title>{{ $t('Duplicate') }}</v-alert-title>
                                            {{ $t('DuplicateFoundInfo') }}
                                            <v-list>
                                                <v-list-item :to="{name: 'view_recipe', params: {id: r.id}}" v-for="r in importResponse.duplicates" :key="r.id"> {{ r.name }} (#{{r.id}})</v-list-item>
                                            </v-list>
                                        </v-alert>
                                    </v-card-text>
                                </v-card>
                            </v-stepper-window-item>
                            <v-stepper-window-item value="2">
                                <v-row>
                                    <v-col cols="12" md="6">
                                        <h2 class="text-h5">{{ $t('Selected') }}</h2>
                                        <v-img max-height="30vh" :src="importResponse.recipe.imageUrl"></v-img>
                                    </v-col>
                                    <v-col cols="12" md="6">
                                        <h2 class="text-h5">{{ $t('Available') }}</h2>
                                        <v-row dense>
                                            <v-col cols="4" v-for="i in importResponse.images">
                                                <v-img max-height="10vh" cover aspect-ratio="1" :src="i" @click="importResponse.recipe.imageUrl = i"></v-img>
                                            </v-col>
                                        </v-row>
                                    </v-col>
                                </v-row>
                            </v-stepper-window-item>
                            <v-stepper-window-item value="3">
                                <v-row>
                                    <v-col class="text-center">
                                        <v-btn-group border divided>
                                            <v-btn prepend-icon="fa-solid fa-square-check" @click="setAllKeywordsImportStatus(true)">{{ $t('SelectAll') }}</v-btn>
                                            <v-btn prepend-icon="fa-solid fa-square-minus" @click="setAllKeywordsImportStatus(false)">{{ $t('SelectNone') }}</v-btn>
                                        </v-btn-group>
                                    </v-col>
                                </v-row>

                                <v-row>
                                    <v-col>
                                        <model-select model="Keyword" v-model="keywordSelect">
                                            <template #append>
                                                <v-btn icon="$add" color="success"
                                                       @click="keywordSelect.importKeyword = true; importResponse.recipe.keywords.push(keywordSelect); keywordSelect= null"
                                                       :disabled="keywordSelect == null"></v-btn>
                                            </template>
                                        </model-select>
                                    </v-col>
                                </v-row>

                                <v-list>
                                    <v-list-item border v-for="k in importResponse.recipe.keywords" :key="k" :class="{'bg-success': k.importKeyword}"
                                                 @click="k.importKeyword = !k.importKeyword">
                                        {{ k.label }}
                                        <template #append>
                                            <v-checkbox-btn :model-value="k.importKeyword"></v-checkbox-btn>
                                        </template>
                                    </v-list-item>
                                </v-list>


                            </v-stepper-window-item>
                            <v-stepper-window-item value="4">
                                <v-row>
                                    <v-col class="text-center">
                                        <v-btn-group border divided>
                                            <v-btn prepend-icon="fa-solid fa-shuffle" @click="autoSortIngredients()"><span v-if="!mobile">{{ $t('Auto_Sort') }}</span></v-btn>
                                            <v-btn prepend-icon="fa-solid fa-maximize" @click="splitAllSteps('\n')"><span v-if="!mobile">{{ $t('Split') }}</span></v-btn>
                                            <v-btn prepend-icon="fa-solid fa-minimize" @click="mergeAllSteps()"><span v-if="!mobile">{{ $t('Merge') }}</span></v-btn>
                                        </v-btn-group>
                                    </v-col>
                                </v-row>
                                <v-row v-for="(s,i) in importResponse.recipe.steps" :key="i">
                                    <v-col cols="12">
                                        <v-chip color="primary">#{{ i + 1 }}</v-chip>
                                        <v-btn variant="plain" size="small" icon class="float-right">
                                            <v-icon icon="$menu"></v-icon>
                                            <v-menu activator="parent">
                                                <v-list>
                                                    <v-list-item prepend-icon="$delete" @click="deleteStep(s)">{{ $t('Delete') }}</v-list-item>
                                                    <v-list-item prepend-icon="fa-solid fa-maximize" @click="splitStep(s, '\n')">{{ $t('Split') }}</v-list-item>
                                                </v-list>
                                            </v-menu>
                                        </v-btn>
                                    </v-col>
                                    <v-col cols="12" md="6">
                                        <v-list>
                                            <vue-draggable v-model="s.ingredients" group="ingredients" handle=".drag-handle" empty-insert-threshold="25">
                                                <v-list-item v-for="i in s.ingredients" border>
                                                    <v-icon size="small" class="drag-handle cursor-grab" icon="$dragHandle"></v-icon>
                                                    {{ i.amount }} <span v-if="i.unit">{{ i.unit.name }}</span> <span v-if="i.food">{{ i.food.name }}</span>
                                                    <template #append>
                                                        <v-btn variant="plain" size="small" icon class="float-right">
                                                            <v-icon icon="$menu"></v-icon>
                                                            <v-menu activator="parent">
                                                                <v-list>
                                                                    <v-list-item prepend-icon="$edit" @click="editingIngredient = i; dialog=true">{{ $t('Edit') }}</v-list-item>
                                                                    <v-list-item prepend-icon="$delete" @click="deleteIngredient(s,i)">{{ $t('Delete') }}</v-list-item>
                                                                </v-list>
                                                            </v-menu>
                                                        </v-btn>
                                                    </template>
                                                </v-list-item>
                                            </vue-draggable>
                                        </v-list>
                                    </v-col>
                                    <v-col cols="12" md="6">
                                        <v-textarea class="mt-2" v-model="s.instruction"></v-textarea>
                                    </v-col>
                                </v-row>
                                <v-row>
                                    <v-col class="text-center">
                                        <v-btn icon="$add" color="create" @click="addStep()"></v-btn>
                                    </v-col>
                                </v-row>
                                <v-dialog max-width="450px" v-model="dialog">
                                    <v-card>
                                        <v-closable-card-title v-model="dialog" :title="$t('Ingredient Editor')"></v-closable-card-title>
                                        <v-card-text>
                                            <v-text-field :label="$t('Original_Text')" v-model="editingIngredient.originalText" disabled></v-text-field>
                                            <v-text-field :label="$t('Amount')" v-model="editingIngredient.amount"></v-text-field>

                                            <v-text-field :label="$t('Unit')" v-model="editingIngredient.unit.name" v-if="editingIngredient.unit"></v-text-field>
                                            <v-btn prepend-icon="$create" color="create" v-else>{{ $t('Unit') }}</v-btn>

                                            <v-text-field :label="$t('Food')" v-model="editingIngredient.food.name"></v-text-field>
                                            <v-text-field :label="$t('Note')" v-model="editingIngredient.note"></v-text-field>
                                        </v-card-text>
                                        <v-card-actions>
                                            <v-btn class="float-right" color="save" @click="dialog = false">{{ $t('Save') }}</v-btn>
                                        </v-card-actions>
                                    </v-card>
                                </v-dialog>

                            </v-stepper-window-item>
                            <v-stepper-window-item value="5">
                                <v-card :loading="loading || fileApiLoading">
                                    <v-card-title>{{ importResponse.recipe.name }}</v-card-title>
                                    <v-row>
                                        <v-col cols="12" md="6">
                                            <v-img v-if="importResponse.recipe.imageUrl" :src="importResponse.recipe.imageUrl"></v-img>
                                        </v-col>
                                        <v-col cols="12" md="6">
                                            <v-text-field :label="$t('Name')" v-model="importResponse.recipe.name"></v-text-field>
                                            <v-number-input :label="$t('Servings')" v-model="importResponse.recipe.servings"></v-number-input>
                                            <v-text-field :label="$t('ServingsText')" v-model="importResponse.recipe.servingsText"></v-text-field>
                                            <v-textarea :label="$t('Description')" v-model="importResponse.recipe.description" clearable></v-textarea>
                                        </v-col>
                                    </v-row>

                                </v-card>
                            </v-stepper-window-item>
                        </v-stepper-window>

                        <v-stepper-actions >
                            <template #prev>
                                <v-btn @click="stepper = (parseInt(stepper) - 1).toString()">Zurück</v-btn>
                            </template>
                            <template #next>
                                <v-btn @click="createRecipeFromImport()" color="success" :disabled="Object.keys(importResponse).length == 0"  v-if="stepper == '1'">{{$t('Import')}}</v-btn>
                                <v-btn @click="stepper = (parseInt(stepper) + 1).toString()" :disabled="Object.keys(importResponse).length == 0" v-if="stepper != '5'">
                                    {{stepper == '1' ? $t('Edit') : $t('Next')}}
                                </v-btn>
                                <v-btn @click="createRecipeFromImport()" color="success" :disabled="false"  v-if="stepper == '5'">{{$t('Import')}}</v-btn>
                            </template>
                        </v-stepper-actions>
                    </template>

                </v-stepper>


            </v-col>
        </v-row>
    </v-container>
</template>

<script lang="ts" setup>

import {nextTick, ref} from "vue";
import {ApiApi, Keyword, RecipeFromSourceResponse, type SourceImportIngredient, SourceImportKeyword, SourceImportStep} from "@/openapi";
import {ErrorMessageType, MessageType, useMessageStore} from "@/stores/MessageStore";
import {useRouter} from "vue-router";
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
import {VueDraggable} from "vue-draggable-plus";
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import KeywordsBar from "@/components/display/KeywordsBar.vue";
import {VNumberInput} from 'vuetify/labs/VNumberInput'
import {useFileApi} from "@/composables/useFileApi";
import ModelSelect from "@/components/inputs/ModelSelect.vue";
import {useDisplay} from "vuetify";

const {mobile} = useDisplay()
const router = useRouter()
const {updateRecipeImage, convertImageToRecipe, fileApiLoading} = useFileApi()

const stepper = ref("1")
const dialog = ref(false)
const loading = ref(false)
const importUrl = ref("")



const image = ref<null|File>(null)

const importResponse = ref({} as RecipeFromSourceResponse)
const keywordSelect = ref<null | SourceImportKeyword>(null)
const editingIngredient = ref({} as SourceImportIngredient)

/**
 * call server to load recipe from a given URl
 */
function loadRecipeFromUrl() {
    let api = new ApiApi()
    loading.value = true
    api.apiRecipeFromSourceCreate({recipeFromSource: {url: importUrl.value}}).then(r => {
        importResponse.value = r
    }).catch(err => {
        useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
    }).finally(() => {
        loading.value = false
    })
}

function uploadAndConvertImage(){
    if(image.value != null){
        convertImageToRecipe(image.value).then(r => {
            importResponse.value = r
        })
    }
}

/**
 * create recipe in database
 */
function createRecipeFromImport() {
    let api = new ApiApi()

    if (importResponse.value.recipe) {
        loading.value = true
        importResponse.value.recipe.keywords = importResponse.value.recipe.keywords.filter(k => k.importKeyword)

        api.apiRecipeCreate({recipe: importResponse.value.recipe}).then(recipe => {
            updateRecipeImage(recipe.id!, null, importResponse.value.recipe?.imageUrl).then(r => {
                router.push({name: 'view_recipe', params: {id: recipe.id}})
            })
        }).catch(err => {
            useMessageStore().addError(ErrorMessageType.CREATE_ERROR, err)
        }).finally(() => {
            loading.value = false
        })
    }
}

/**
 * deletes the given step from the local recipe
 * @param step step to delete
 */
function deleteStep(step: SourceImportStep) {
    if (importResponse.value.recipe) {
        importResponse.value.recipe.steps.splice(importResponse.value.recipe.steps.findIndex(x => x === step), 1)
    }
}

/**
 * utility function used by splitAllSteps and splitStep to split a single step object into multiple step objects
 * @param step step to split
 * @param split_character character to use as a delimiter between steps
 */
function splitStepObject(step: SourceImportStep, split_character: string) {
    let steps: SourceImportStep[] = []
    step.instruction.split(split_character).forEach(part => {
        if (part.trim() !== '') {
            steps.push({instruction: part, ingredients: [], showIngredientsTable: useUserPreferenceStore().userSettings.showStepIngredients!})
        }
    })
    steps[0].ingredients = step.ingredients // put all ingredients from the original step in the ingredients of the first step of the split step list
    return steps
}

/**
 * Splits all steps of a given recipe_json at the split character (e.g. \n or \n\n)
 * @param split_character character to split steps at
 */
function splitAllSteps(split_character: string) {
    let steps: SourceImportStep[] = []
    if (importResponse.value.recipe) {
        importResponse.value.recipe.steps.forEach(step => {
            steps = steps.concat(splitStepObject(step, split_character))
        })
        importResponse.value.recipe.steps = steps
    } else {
        useMessageStore().addMessage(MessageType.ERROR, "no steps found to split")
    }

}

/**
 * Splits the given step at the split character (e.g. \n or \n\n)
 * @param step step to split
 * @param split_character character to use as a delimiter between steps
 */
function splitStep(step: SourceImportStep, split_character: string) {
    if (importResponse.value.recipe) {
        let old_index = importResponse.value.recipe.steps.findIndex(x => x === step)
        let new_steps = splitStepObject(step, split_character)
        importResponse.value.recipe.steps.splice(old_index, 1, ...new_steps)
    } else {
        useMessageStore().addMessage(MessageType.ERROR, "no steps found to split")
    }
}

/**
 * Merge all steps of a given recipe_json into one
 */
function mergeAllSteps() {
    let step = {instruction: '', ingredients: [], showIngredientsTable: useUserPreferenceStore().userSettings.showStepIngredients!} as SourceImportStep
    if (importResponse.value.recipe) {
        importResponse.value.recipe.steps.forEach(s => {
            step.instruction += s.instruction + '\n'
            step.ingredients = step.ingredients.concat(s.ingredients)
        })
        importResponse.value.recipe.steps = [step]
    } else {
        useMessageStore().addMessage(MessageType.ERROR, "no steps found to split")
    }
}

/**
 * Merge two steps (the given and next one)
 */
function mergeStep(step: SourceImportStep) {
    if (importResponse.value.recipe) {
        let step_index = importResponse.value.recipe.steps.findIndex(x => x === step)
        let removed_steps = importResponse.value.recipe.steps.splice(step_index, 2)

        importResponse.value.recipe.steps.splice(step_index, 0, {
            instruction: removed_steps.flatMap(x => x.instruction).join('\n'),
            ingredients: removed_steps.flatMap(x => x.ingredients),
            showIngredientsTable: useUserPreferenceStore().userSettings.showStepIngredients!
        })
    } else {
        useMessageStore().addMessage(MessageType.ERROR, "no steps found to split")
    }

}

/**
 * deletes the given ingredient from the given step
 * @param step step to delete ingredient from
 * @param ingredient ingredient to delete
 */
function deleteIngredient(step: SourceImportStep, ingredient: SourceImportIngredient) {
    step.ingredients = step.ingredients.filter(i => i != ingredient)
}

/**
 * automatically assign ingredients to steps based on text matching
 */
function autoSortIngredients() {
    if (importResponse.value.recipe) {
        let ingredients = importResponse.value.recipe.steps.flatMap(s => s.ingredients)
        importResponse.value.recipe.steps.forEach(s => s.ingredients = [])

        ingredients.forEach(i => {
            let found = false
            importResponse.value.recipe!.steps.forEach(s => {
                if (s.instruction.includes(i.food.name.trim()) && !found) {
                    found = true
                    s.ingredients.push(i)
                }
            })
            if (!found) {
                importResponse.value.recipe!.steps[0].ingredients.push(i)
            }
            // TODO implement a new "second try" algorithm if no exact match was found
            /*

             if (!found) {
                let best_match = {rating: 0, step: importResponse.value.recipe.steps[0]}
                importResponse.value.recipe.steps.forEach(s => {

                    let match = stringSimilarity.findBestMatch(i.food.name.trim(), s.instruction.split(' '))

                    if (match.bestMatch.rating > best_match.rating) {
                        best_match = {rating: match.bestMatch.rating, step: s}
                    }
                })
                best_match.step.ingredients.push(i)
                found = true
            }
             */
        })
    } else {
        useMessageStore().addMessage(MessageType.ERROR, "no steps found to split")
    }
}

/**
 * set the import status for all keywords to the given status
 * @param status if keyword should be imported or not
 */
function setAllKeywordsImportStatus(status: boolean) {
    importResponse.value.recipe?.keywords.forEach(keyword => {
        keyword.importKeyword = status
    })
}

/**
 * add a new (empty) step at the end of the step list
 */
function addStep() {
    importResponse.value.recipe?.steps.push({} as SourceImportStep)
}

</script>

<style scoped>

</style>