<script setup lang="ts">
import { trainingReportSchema, courseEventAttendeeSchema } from '@shared/schemas/trainingReportSchema'
import { Course, CourseAttendee, CourseAttendeeRole, CourseEventDetails } from '@shared/types/course'
import { useForm, useFieldArray, FieldArray as VeeFieldArray, ErrorMessage, Field as VeeField } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import { getAllAttendeeRoles, getAllTrainings, postTrainingReport, putTrainingReport } from '@/api/trainingReport'
import { getAllLightMembers, getLightMembers, getMembers } from '@/api/member'
import { Member, MemberLight } from '@shared/types/member'

import FieldGroup from '../ui/field/FieldGroup.vue'
import Field from '../ui/field/Field.vue'
import FieldLabel from '../ui/field/FieldLabel.vue'
import FieldError from '../ui/field/FieldError.vue'
import Button from '../ui/button/Button.vue'
import Textarea from '../ui/textarea/Textarea.vue'
import { Check, Plus, X } from 'lucide-vue-next';
import FieldSet from '../ui/field/FieldSet.vue'
import FieldLegend from '../ui/field/FieldLegend.vue'
import FieldDescription from '../ui/field/FieldDescription.vue'
import Checkbox from '../ui/checkbox/Checkbox.vue'
import { configure } from 'vee-validate'
import { ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList } from "@/components/ui/combobox"
import Popover from "@/components/ui/popover/Popover.vue";
import PopoverTrigger from "@/components/ui/popover/PopoverTrigger.vue";
import PopoverContent from "@/components/ui/popover/PopoverContent.vue";
import Combobox from '../ui/combobox/Combobox.vue'
import Tooltip from '../tooltip/Tooltip.vue'
import Spinner from '../ui/spinner/Spinner.vue'

const props = withDefaults(defineProps<{
    mode?: 'create' | 'edit';
    report?: CourseEventDetails | null;
    reportId?: number | null;
}>(), {
    mode: 'create',
    report: null,
    reportId: null,
})

const emit = defineEmits(['submit'])

function toFormDate(dateValue: Date | string | null | undefined): string {
    if (!dateValue) return "";
    const d = new Date(dateValue);
    if (isNaN(d.getTime())) return "";
    return d.toISOString().split('T')[0];
}

function toFormValues(report: CourseEventDetails) {
    return {
        course_id: report.course_id,
        event_date: toFormDate(report.event_date),
        remarks: report.remarks ?? "",
        attendees: (report.attendees ?? []).map((attendee) => ({
            attendee_id: attendee.attendee_id,
            attendee_role_id: attendee.attendee_role_id,
            passed_bookwork: !!attendee.passed_bookwork,
            passed_qual: !!attendee.passed_qual,
            remarks: attendee.remarks ?? "",
        })),
    };
}


const { handleSubmit, resetForm, errors, values, setFieldValue } = useForm({
    validationSchema: toTypedSchema(trainingReportSchema),
    validateOnMount: false,
    initialValues: {
        course_id: null,
        event_date: "",
        remarks: "",
        attendees: [],
    }
})

const hydratedReportId = ref<number | null>(null);
const comboboxRenderEpoch = ref(0);

watch(() => props.report, (report) => {
    hydratedReportId.value = null;

    if (!report) {
        if (props.mode === 'create') {
            resetForm();
            comboboxRenderEpoch.value++;
        }
        return;
    }

    resetForm({
        values: toFormValues(report),
    });

    comboboxRenderEpoch.value++;
}, { immediate: true });

function hydrateEditValuesWhenOptionsReady() {
    if (props.mode !== 'edit' || !props.report) {
        return;
    }

    if (!trainings.value || !members.value || !eventRoles.value) {
        return;
    }

    const reportId = Number(props.report.id);
    if (!Number.isFinite(reportId)) {
        return;
    }

    if (hydratedReportId.value === reportId) {
        return;
    }

    resetForm({
        values: toFormValues(props.report),
    });

    hydratedReportId.value = reportId;
    comboboxRenderEpoch.value++;
}

// watch(errors, (newErrors) => {
//     console.log(newErrors)
// }, { deep: true })

// watch(values, (newErrors) => {
//     console.log(newErrors.attendees)
// }, { deep: true })

watch(() => values.course_id, (newCourseId, oldCourseId) => {
    if (!oldCourseId) return;

    values.attendees.forEach((a, index) => {
        // @ts-ignore
        setFieldValue(`attendees[${index}].passed_bookwork`, false);
        // @ts-ignore
        setFieldValue(`attendees[${index}].passed_qual`, false);
    });
});

const submitForm = handleSubmit(onSubmit);

function toMySQLDateTime(date: Date): string {
    return date
        .toISOString()                 // 2025-11-19T00:00:00.000Z
        .slice(0, 23)                  // keep milliseconds → 2025-11-19T00:00:00.000
        .replace("T", " ") + "000";    // becomes → 2025-11-19 00:00:00.000000
}

const submitting = ref(false);
async function onSubmit(vals) {
    //catch double submit
    if (submitting.value) return;
    submitting.value = true;
    try {
        const clean: CourseEventDetails = {
            ...vals,
            event_date: new Date(vals.event_date),
        }

        if (props.mode === 'edit') {
            const id = Number(props.reportId);
            if (!id || Number.isNaN(id)) {
                throw new Error('Cannot edit report without a valid reportId');
            }

            await putTrainingReport(id, clean);
            emit("submit", id);
        } else {
            await postTrainingReport(clean).then((newID) => {
                emit("submit", newID);
            });
        }
    } catch (err) {
        console.error("There was an error submitting the training report", err);
    } finally {
        submitting.value = false;
    }
}

const { remove, push, fields } = useFieldArray('attendees');

const selectedCourse = computed<Course | undefined>(() => { return trainings.value?.find(c => c.id == values.course_id) })

const trainings = ref<Course[] | null>(null);
const members = ref<MemberLight[] | null>(null);
const eventRoles = ref<CourseAttendeeRole[] | null>(null);

onMounted(async () => {
    trainings.value = await getAllTrainings();
    members.value = await getAllLightMembers();
    eventRoles.value = await getAllAttendeeRoles();

    hydrateEditValuesWhenOptionsReady();
})

watch([trainings, members, eventRoles, () => props.report], () => {
    hydrateEditValuesWhenOptionsReady();
});

const selectCourse = ref(false);
const openMap = reactive<Record<string, boolean>>({})

const memberMap = computed(() =>
    Object.fromEntries(
        members.value?.map(m => [m.id, m.displayName || m.username]) ?? []
    )
)

const memberSearch = ref('')

const MAX_RESULTS = 50

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

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

    return results
})

</script>
<template>
    <form id="trainingForm" @submit.prevent="submitForm" class="flex flex-col gap-5">

        <div class="flex gap-5">
            <div class="flex-1">
                <FieldGroup>
                    <VeeField v-slot="{ field, errors }" name="course_id">
                        <Field :data-invalid="!!errors.length">
                            <FieldLabel class="scroll-m-20 text-lg tracking-tight">Training Course</FieldLabel>
                            <Combobox :model-value="field.value" @update:open="selectCourse = $event"
                                :key="`course-${comboboxRenderEpoch}`"
                                :open="selectCourse" @update:model-value="(v) => {
                                    field.onChange(v);
                                    selectCourse = false
                                }" class="w-full">
                                <ComboboxAnchor class="w-full">
                                    <ComboboxInput @focus="selectCourse = true" placeholder="Search courses..."
                                        class="w-full pl-3" :display-value="(id) => {
                                            const c = trainings?.find(t => Number(t.id) === Number(id))
                                            return c ? c.name : '';
                                        }" />
                                </ComboboxAnchor>

                                <ComboboxList class="w-full">
                                    <ComboboxEmpty class="text-muted-foreground w-full">No results</ComboboxEmpty>
                                    <ComboboxGroup>
                                        <div class="max-h-80 overflow-y-scroll scrollbar-themed min-w-md">
                                            <template v-for="course in trainings" :key="course.id">
                                                <ComboboxItem :value="course.id"
                                                    class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
                                                    {{ course.name }}
                                                    <ComboboxItemIndicator
                                                        class="absolute left-2 inline-flex items-center">
                                                        <Check class="h-4 w-4" />
                                                    </ComboboxItemIndicator>
                                                </ComboboxItem>
                                            </template>
                                        </div>
                                    </ComboboxGroup>
                                </ComboboxList>
                            </Combobox>
                            <div class="h-4">
                                <FieldError v-if="errors.length" :errors="errors" />
                            </div>
                        </Field>
                    </VeeField>
                </FieldGroup>
            </div>

            <div class="w-[150px]">
                <FieldGroup>
                    <VeeField v-slot="{ field, errors }" name="event_date">
                        <Field :data-invalid="!!errors.length">
                            <FieldLabel class="scroll-m-20 text-lg tracking-tight">Event Date</FieldLabel>
                            <input type="date" v-bind="field"
                                class="h-9 border rounded p-2 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] bg-background outline-none" />
                            <div class="h-4">
                                <FieldError v-if="errors.length" :errors="errors" />
                            </div>
                        </Field>
                    </VeeField>
                </FieldGroup>
            </div>
        </div>

        <VeeFieldArray name="attendees" v-slot="{ fields, push, remove }">
            <FieldSet class="gap-4">
                <div class="flex flex-col gap-2">
                    <FieldLegend class="scroll-m-20 text-lg tracking-tight mb-0">Attendees</FieldLegend>
                    <FieldDescription class="mb-0">Add members who attended this session.</FieldDescription>
                    <div class="h-4">
                        <div class="text-red-500 text-sm"
                            v-if="errors.attendees && typeof errors.attendees === 'string'">
                            {{ errors.attendees }}
                        </div>
                    </div>
                </div>


                <FieldGroup class="gap-4">

                    <!-- Column Headers -->
                    <div class="relative">
                        <div
                            class="grid grid-cols-[180px_155px_65px_41px_1fr_auto] gap-3 font-medium text-sm text-muted-foreground">

                            <div>Member</div>
                            <div>Role</div>

                            <!-- Bookwork -->
                            <div class="text-center">Bookwork</div>

                            <!-- Qual -->
                            <div class="text-center">Qual</div>

                            <div>Remarks</div>
                            <div></div> <!-- empty for remove button -->
                        </div>

                        <!-- FLOATING SUPERHEADER -->
                        <div class="absolute left-[calc(180px+155px+65px/2)] -top-5 
           w-[106px] text-center text-xs font-medium text-muted-foreground 
           pointer-events-none">
                            ──── Pass ────
                        </div>
                    </div>


                    <!-- Attendee Rows -->
                    <template v-for="(field, index) in fields" :key="field.key">

                        <div class="grid grid-cols-[180px_160px_50px_50px_1fr_auto] gap-3 items-center">

                            <!-- Member Select -->
                            <VeeField :name="`attendees[${index}].attendee_id`" v-slot="{ field: f, errors: e }">
                                <div>
                                    <Combobox :model-value="f.value"
                                        :key="`member-${field.key}-${comboboxRenderEpoch}`"
                                        @update:open="openMap['member-' + field.key] = $event"
                                        :open="openMap['member-' + field.key]" @update:model-value="(v) => {
                                            f.onChange(v);
                                            openMap['member-' + field.key] = false
                                        }" class="w-full">
                                        <ComboboxAnchor class="w-full">
                                            <ComboboxInput
                                                @focus="() => { openMap['member-' + field.key] = true; memberSearch = memberMap[f.value] }"
                                                placeholder="Search members..." class="w-full pl-3"
                                                :display-value="(id) => memberMap[String(id)] || ''"
                                                @input="memberSearch = $event.target.value" />
                                        </ComboboxAnchor>
                                        <ComboboxList class="w-full">
                                            <ComboboxEmpty class="text-muted-foreground w-full">No results
                                            </ComboboxEmpty>
                                            <ComboboxGroup>
                                                <div class="max-h-80 overflow-y-scroll scrollbar-themed min-w-3xs">
                                                    <template v-for="m in filteredMembers" :key="m.id">
                                                        <ComboboxItem :value="m.id"
                                                            class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
                                                            {{ m.displayName || m.username }}
                                                            <ComboboxItemIndicator
                                                                class="absolute left-2 inline-flex items-center">
                                                                <Check class="h-4 w-4" />
                                                            </ComboboxItemIndicator>
                                                        </ComboboxItem>
                                                    </template>
                                                </div>
                                            </ComboboxGroup>
                                        </ComboboxList>
                                    </Combobox>
                                    <div class="h-4">
                                        <FieldError v-if="e.length" :errors="e" />
                                    </div>
                                </div>
                            </VeeField>

                            <!-- Role Select -->
                            <VeeField :name="`attendees[${index}].attendee_role_id`" v-slot="{ field: f, errors: e }">
                                <div>
                                    <Combobox :model-value="f.value"
                                        :key="`role-${field.key}-${comboboxRenderEpoch}`"
                                        @update:open="openMap['role-' + field.key] = $event"
                                        :open="openMap['role-' + field.key]" @update:model-value="(v) => {
                                            f.onChange(v);
                                            openMap['role-' + field.key] = false
                                        }" class="w-full">
                                        <ComboboxAnchor class="w-full">
                                            <ComboboxInput @focus="openMap['role-' + field.key] = true"
                                                placeholder="Search roles..." class="w-full pl-3" :display-value="(id) => {
                                                    const er = eventRoles?.find(t => Number(t.id) === Number(id))
                                                    return er?.name;
                                                }" />
                                        </ComboboxAnchor>
                                        <ComboboxList class="w-full">
                                            <ComboboxEmpty class="text-muted-foreground w-full">No results
                                            </ComboboxEmpty>
                                            <ComboboxGroup>
                                                <div class="max-h-80 overflow-y-scroll scrollbar-themed min-w-3xs">
                                                    <template v-for="r in eventRoles" :key="r.id">
                                                        <ComboboxItem :value="r.id"
                                                            class="data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative cursor-pointer select-none px-2 py-1.5 w-full">
                                                            <div class="flex justify-between w-full gap-8">
                                                                <p>{{ r.name }}</p>
                                                                <p class="text-muted-foreground">{{ r.description }}</p>
                                                            </div>
                                                            <ComboboxItemIndicator
                                                                class="absolute left-2 inline-flex items-center">
                                                                <Check class="h-4 w-4" />
                                                            </ComboboxItemIndicator>
                                                        </ComboboxItem>
                                                    </template>
                                                </div>
                                            </ComboboxGroup>
                                        </ComboboxList>
                                    </Combobox>

                                    <div class="h-4">
                                        <FieldError v-if="e.length" :errors="e" />
                                    </div>
                                </div>
                            </VeeField>

                            <!-- Bookwork Checkbox -->
                            <VeeField v-slot="{ field }" :name="`attendees[${index}].passed_bookwork`" type="checkbox"
                                :value="false" :unchecked-value="true">
                                <div class="flex flex-col items-center">
                                    <Tooltip :open="!selectedCourse?.hasBookwork"
                                        message="This course does not have bookwork">
                                        <Checkbox :disabled="!selectedCourse?.hasBookwork"
                                            :name="`attendees[${index}].passed_bookwork`" :model-value="!field.checked"
                                            @update:model-value="field['onUpdate:modelValue']">
                                        </Checkbox>
                                    </Tooltip>
                                    <div class="h-4">
                                    </div>
                                </div>
                            </VeeField>

                            <!-- Qual Checkbox -->
                            <VeeField v-slot="{ field }" :name="`attendees[${index}].passed_qual`" type="checkbox"
                                :value="false" :unchecked-value="true">
                                <div class="flex flex-col items-center">
                                    <Tooltip :open="!selectedCourse?.hasQual"
                                        message="This course does not have a qualification">
                                        <Checkbox :disabled="!selectedCourse?.hasQual"
                                            :name="`attendees[${index}].passed_qual`" :model-value="!field.checked"
                                            @update:model-value="field['onUpdate:modelValue']"></Checkbox>
                                    </Tooltip>
                                    <div class="h-4">
                                    </div>
                                </div>
                            </VeeField>

                            <!-- Remarks -->
                            <VeeField :name="`attendees[${index}].remarks`" v-slot="{ field: f, errors: e }">
                                <div class="flex flex-col">
                                    <textarea v-bind="f"
                                        class="h-[38px] resize-none border rounded p-2 w-full focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] bg-background outline-none"
                                        placeholder="Optional remarks"></textarea>
                                    <div class="h-4">
                                        <FieldError v-if="e.length" :errors="e" />
                                    </div>
                                </div>
                            </VeeField>

                            <div>
                                <!-- Remove button -->
                                <Button type="button" variant="ghost" size="sm" @click="remove(index)"
                                    class="self-center">
                                    <X :size="10" />
                                </Button>
                                <div class="h-4">
                                </div>
                            </div>
                        </div>
                    </template>
                </FieldGroup>


                <Button type="button" size="sm" variant="outline"
                    @click="push({ attendee_id: null, attendee_role_id: null, passed_bookwork: false, passed_qual: false, remarks: '' })">
                    <Plus class="mr-1 h-4 w-4" />
                    Add Attendee
                </Button>
            </FieldSet>
        </VeeFieldArray>

        <FieldGroup class="pt-3">
            <VeeField v-slot="{ field, errors }" name="remarks">
                <Field :data-invalid="!!errors.length">
                    <FieldLabel class="scroll-m-20 text-lg tracking-tight">Remarks</FieldLabel>
                    <Textarea v-bind="field" placeholder="Any remarks about this training event..."
                        autocomplete="off" />
                    <FieldError v-if="errors.length" :errors="errors" />
                </Field>
            </VeeField>
        </FieldGroup>
        <div class="flex gap-3 justify-end">
            <Button type="button" variant="outline" @click="resetForm">Reset</Button>
            <Button type="submit" form="trainingForm" :disabled="submitting" class="w-35">
                <span class="flex items-center gap-2" v-if="submitting">
                    <Spinner></Spinner> {{ props.mode === 'edit' ? 'Saving…' : 'Submitting…' }}
                </span>
                <span v-else>{{ props.mode === 'edit' ? 'Save Changes' : 'Submit' }}</span>
            </Button>
        </div>
    </form>
</template>
