<script setup lang="ts">
import { batchPromotionSchema } from '@shared/schemas/promotionSchema';
import { useForm, Field as VeeField, FieldArray as VeeFieldArray } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/zod';
import FieldSet from '../ui/field/FieldSet.vue';
import FieldLegend from '../ui/field/FieldLegend.vue';
import FieldDescription from '../ui/field/FieldDescription.vue';
import FieldGroup from '../ui/field/FieldGroup.vue';
import Combobox from '../ui/combobox/Combobox.vue';
import ComboboxAnchor from '../ui/combobox/ComboboxAnchor.vue';
import ComboboxInput from '../ui/combobox/ComboboxInput.vue';
import ComboboxList from '../ui/combobox/ComboboxList.vue';
import ComboboxEmpty from '../ui/combobox/ComboboxEmpty.vue';
import ComboboxGroup from '../ui/combobox/ComboboxGroup.vue';
import ComboboxItem from '../ui/combobox/ComboboxItem.vue';
import ComboboxItemIndicator from '../ui/combobox/ComboboxItemIndicator.vue';
import { computed, onMounted, ref } from 'vue';
import { MemberLight } from '@shared/types/member';
import { Check, Plus, X } from 'lucide-vue-next';
import Button from '../ui/button/Button.vue';
import FieldError from '../ui/field/FieldError.vue';
import { getAllLightMembers } from '@/api/member';
import { Rank } from '@shared/types/rank';
import { getAllRanks, submitRankChange } from '@/api/rank';
import { error } from 'console';
import Input from '../ui/input/Input.vue';
import Field from '../ui/field/Field.vue';

const { handleSubmit, errors, values, resetForm, setFieldValue, submitCount } = useForm({
    validationSchema: toTypedSchema(batchPromotionSchema),
    validateOnMount: false,
})

const submitting = ref(false);

const submitForm = handleSubmit(
    async (vals) => {
        if (submitting.value) return;
        submitting.value = true;
        try {
            let output = vals;
            output.promotions.map(p => p.start_date = new Date(p.start_date).toISOString())
            await submitRankChange(output);
            formSubmitted.value = true;
            emit("submitted");
        } catch (error) {
            submitError.value = error;
            console.error(error);
        } finally {
            submitting.value = false;
        }
    }
);

const emit = defineEmits<{
    submitted: [void]
}>();

const submitError = ref<string>(null);
const formSubmitted = ref(false);

const allmembers = ref<MemberLight[]>([]);
const allRanks = ref<Rank[]>([]);

const memberById = computed(() => {
    const map = new Map<number, MemberLight>();
    for (const m of allmembers.value) {
        map.set(m.id, m);
    }
    return map;
});

const rankById = computed(() => {
    const map = new Map<number, Rank>();
    for (const r of allRanks.value) {
        map.set(r.id, r);
    }
    return map;
});

const memberSearch = ref('');
const rankSearch = ref('');

const filteredMembers = computed(() => {
    const q = memberSearch?.value?.toLowerCase() ?? ""
    const results: MemberLight[] = []

    for (const m of allmembers.value ?? []) {
        if (!q || (m.displayName || m.username).toLowerCase().includes(q)) {
            results.push(m)
            if (results.length >= 50) break
        }
    }

    return results
})

const filteredRanks = computed(() =>
    filterRanks(rankSearch.value)
);

function filterRanks(query: string): Rank[] {
    if (!query) return allRanks.value;

    const q = query.toLowerCase();
    return allRanks.value.filter(r =>
        r.name.toLowerCase().includes(q) ||
        r.short_name.toLowerCase().includes(q)
    );
}

onMounted(async () => {
    allmembers.value = await getAllLightMembers()
    allRanks.value = await getAllRanks();
})

function setAllToday() {
    const today = () => {
        const d = new Date()
        const year = d.getFullYear()
        const month = String(d.getMonth() + 1).padStart(2, '0')
        const day = String(d.getDate()).padStart(2, '0')

        return `${year}-${month}-${day}`
    }

    values.promotions?.forEach((_, index) => {
        // @ts-ignore
        setFieldValue(`promotions[${index}].start_date`, today())
    })
}
</script>

<template>
    <div class="w-xl">
        <form v-if="!formSubmitted" id="trainingForm" @submit.prevent="submitForm"
            class="w-full min-w-0 flex flex-col gap-4">
            <div>
                <FieldLegend class="scroll-m-20 text-2xl font-semibold tracking-tight">
                    Promotion Form
                </FieldLegend>
            </div>
            <VeeFieldArray name="promotions" v-slot="{ fields, push, remove }">
                <FieldSet class="w-full min-w-0">
                    <div class="flex flex-col gap-2">
                        <!-- TABLE SHELL -->
                        <div class="">
                            <FieldGroup class="">
                                <!-- HEADER -->
                                <div class="grid grid-cols-[200px_200px_150px_1fr_auto]
                           gap-3 px-1 -mb-4
                           text-sm font-medium text-muted-foreground">
                                    <div>Member</div>
                                    <div>Rank</div>
                                    <div class="flex justify-between">
                                        <p>Date</p><button @click.prevent.stop="setAllToday"
                                            class="cursor-pointer border-1 rounded-full px-3 hover:bg-secondary hover:border-accent">Today</button>
                                    </div>
                                    <div></div>
                                    <div></div>
                                </div>
                                <!-- BODY -->
                                <div class="flex flex-col gap-2">
                                    <div v-for="(row, index) in fields" :key="row.key" class="grid grid-cols-[200px_200px_150px_1fr_auto]
                             gap-3 items-start">
                                        <!-- Member -->
                                        <VeeField :name="`promotions[${index}].member_id`" v-slot="{ field, errors }">
                                            <div class="flex flex-col min-w-0">
                                                <Combobox :model-value="field.value"
                                                    @update:model-value="field.onChange" :ignore-filter="true">
                                                    <ComboboxAnchor>
                                                        <ComboboxInput class="w-full pl-3" placeholder="Search members…"
                                                            :display-value="id =>
                                                                memberById.get(id)?.displayName ||
                                                                memberById.get(id)?.username
                                                                " @input="memberSearch = $event.target.value" />
                                                    </ComboboxAnchor>
                                                    <ComboboxList>
                                                        <ComboboxEmpty>No results</ComboboxEmpty>
                                                        <ComboboxGroup>
                                                            <div
                                                                class="max-h-80 overflow-y-auto min-w-[12rem] scrollbar-themed">
                                                                <ComboboxItem v-for="member in filteredMembers"
                                                                    :key="member.id" :value="member.id">
                                                                    {{ member.displayName || member.username }}
                                                                    <ComboboxItemIndicator>
                                                                        <Check />
                                                                    </ComboboxItemIndicator>
                                                                </ComboboxItem>
                                                            </div>
                                                        </ComboboxGroup>
                                                    </ComboboxList>
                                                </Combobox>
                                                <div class="h-5">
                                                    <FieldError v-if="errors.length" :errors="errors" />
                                                </div>
                                            </div>
                                        </VeeField>
                                        <!-- Rank -->
                                        <VeeField :name="`promotions[${index}].rank_id`" v-slot="{ field, errors }">
                                            <div class="flex flex-col min-w-0">
                                                <Combobox :model-value="field.value"
                                                    @update:model-value="field.onChange" :ignore-filter="true">
                                                    <ComboboxAnchor>
                                                        <ComboboxInput class="w-full pl-3" placeholder="Select rank…"
                                                            :display-value="id => rankById.get(id)?.name"
                                                            @input="rankSearch = $event.target.value" />
                                                    </ComboboxAnchor>
                                                    <ComboboxList>
                                                        <ComboboxEmpty>No results</ComboboxEmpty>
                                                        <ComboboxGroup>
                                                            <div
                                                                class="max-h-80 overflow-y-auto min-w-[12rem] scrollbar-themed">
                                                                <ComboboxItem v-for="rank in filteredRanks"
                                                                    :key="rank.id" :value="rank.id">
                                                                    {{ rank.name }}
                                                                    <ComboboxItemIndicator>
                                                                        <Check />
                                                                    </ComboboxItemIndicator>
                                                                </ComboboxItem>
                                                            </div>
                                                        </ComboboxGroup>
                                                    </ComboboxList>
                                                </Combobox>
                                                <div class="h-5">
                                                    <FieldError v-if="errors.length" :errors="errors" />
                                                </div>
                                            </div>
                                        </VeeField>
                                        <!-- Date -->
                                        <VeeField :name="`promotions[${index}].start_date`" v-slot="{ field, errors }">
                                            <Field>
                                                <div>
                                                    <Input type="date" v-bind="field" />
                                                    <div class="h-5">
                                                        <FieldError v-if="errors.length" :errors="errors" />
                                                    </div>
                                                </div>
                                            </Field>
                                        </VeeField>
                                        <!-- Remove -->
                                        <div class="flex justify-end">
                                            <Button type="button" variant="ghost" size="icon" @click="remove(index)">
                                                <X />
                                            </Button>
                                        </div>
                                    </div>
                                </div>
                            </FieldGroup>
                        </div>
                        <Button type="button" @click="push({})" class="w-full" variant="outline">
                            <Plus /> Member
                        </Button>
                    </div>
                </FieldSet>
            </VeeFieldArray>
            <div class="flex justify-between items-start">
                <VeeField name="approver" v-slot="{ field, errors }">
                    <div class="flex flex-col min-w-0 gap-2">
                        <p>Approved By</p>
                        <Combobox :model-value="field.value" @update:model-value="field.onChange" :ignore-filter="true">
                            <ComboboxAnchor>
                                <ComboboxInput class="w-full pl-3" placeholder="Search members…" :display-value="id =>
                                    memberById.get(id)?.displayName ||
                                    memberById.get(id)?.username
                                    " @input="memberSearch = $event.target.value" />
                            </ComboboxAnchor>
                            <ComboboxList>
                                <ComboboxEmpty>No results</ComboboxEmpty>
                                <ComboboxGroup>
                                    <div class="max-h-80 overflow-y-auto min-w-[12rem] scrollbar-themed">
                                        <ComboboxItem v-for="member in filteredMembers" :key="member.id"
                                            :value="member.id">
                                            {{ member.displayName || member.username }}
                                            <ComboboxItemIndicator>
                                                <Check />
                                            </ComboboxItemIndicator>
                                        </ComboboxItem>
                                    </div>
                                </ComboboxGroup>
                            </ComboboxList>
                        </Combobox>
                        <div class="h-5">
                            <FieldError v-if="errors.length" :errors="errors" />
                        </div>
                    </div>
                </VeeField>
                <div class="flex flex-col items-end gap-2">
                    <div class="h-6" />
                    <Button type="submit" form="trainingForm" :disabled="submitting" class="w-35">
                        <span class="flex items-center gap-2" v-if="submitting">
                            <Spinner></Spinner> Submitting…
                        </span>
                        <span v-else>Submit</span>
                    </Button>
                    <p v-if="submitError" class="text-destructive">{{ submitError }}</p>
                    <div v-else class="h-6 flex justify-end">
                        <p v-if="submitCount > 0 && errors.promotions && typeof errors.promotions === 'string'"
                            class="text-sm text-red-500">
                            {{ errors.promotions }}
                        </p>
                    </div>
                </div>
            </div>
        </form>
        <div v-else>
            <div class="flex flex-col max-w-sm justify-center gap-4 py-24 mx-auto">
                <div class="text-left">
                    <h2 class="text-2xl font-semibold mb-2">Successfully Submitted</h2>
                    <p class="text-muted-foreground">Your promotions have been recorded.</p>
                </div>
                <Button @click="() => { formSubmitted = false; resetForm(); }" variant="secondary">
                    Submit Another
                </Button>
            </div>
        </div>
    </div>
</template>
