<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { Icon } from '@iconify/vue';
import api from '@/utils/api';
import AppRightDialog from '~/components/shared/AppRightDialog.vue';
import { useSnackbarStore } from '~/store/snackbar';
import type {ModalMode,ParentPageOption} from '~/types/setting/menu';
import { useValidation } from '~/composables/useValidation';

const props = withDefaults(
    defineProps<{
        modelValue: boolean;
        mode?: ModalMode;
        pageId?: number | null;
    }>(),
    {
        mode: 'create',
        pageId: null,
    },
);

const emit = defineEmits(['update:modelValue', 'saved']);

const dialog = ref(props.modelValue);

watch(() => props.modelValue, (newValue) => {
    dialog.value = newValue;
});

watch(dialog, (newValue) => {
    if (!newValue) {
        emit('update:modelValue', false);
    }
});

const entryType = ref('main');
const labelName = ref('');

const formRef = ref<any>(null);
const valid = ref(false);
const isSaving = ref(false);
const isLoadingDetail = ref(false);

const snackbarStore = useSnackbarStore();

const { required, isNumber } = useValidation();

const parentModule = ref<number | null>(null);
const parentPageItems = ref<ParentPageOption[]>([]);
const parentPageLoading = ref(false);
const parentPageSearch = ref('');
const url = ref('');
const sortOrder = ref<number | null>(null);
const icon = ref('');
const active = ref(true);

const isDetailMode = computed(() => props.mode === 'detail');
const isEditMode = computed(() => props.mode === 'edit');
const isCreateMode = computed(() => props.mode === 'create');
const isFormDisabled = computed(() => isDetailMode.value || isSaving.value || isLoadingDetail.value);

const titleText = computed(() => {
    if (isCreateMode.value) return 'Tambah Menu';
    if (isEditMode.value) return 'Edit Menu';
    return 'Detail Menu';
});


const submitLabel = computed(() => (isEditMode.value ? 'Update' : 'Simpan'));

const resetForm = () => {
    entryType.value = 'main';
    labelName.value = '';
    parentModule.value = null;
    parentPageItems.value = [];
    parentPageLoading.value = false;
    parentPageSearch.value = '';
    url.value = '';
    sortOrder.value = null;
    icon.value = '';
    active.value = true;
    valid.value = false;
    formRef.value?.resetValidation?.();
};

const resolveParentLevel = async (parentId: number): Promise<number | null> => {
    const fromItems = parentPageItems.value.find((p) => p.id === parentId)?.level;
    if (fromItems != null) return fromItems;

    try {
        const response = await api.get(`/api/v1/roles/pages/${parentId}`);
        const data = response.data?.data;
        return typeof data?.level === 'number' ? data.level : null;
    } catch {
        return null;
    }
};

const fetchParentPages = async (filterText: string) => {
    parentPageLoading.value = true;
    try {
        const response = await api.get('/api/v1/roles/pages/search', {
            params: {
                name: filterText || '',
            },
        });
        const data = response.data?.data;
        parentPageItems.value = Array.isArray(data) ? data : [];
    } catch (error) {
        console.error('Error fetching parent pages:', error);
        parentPageItems.value = [];
    } finally {
        parentPageLoading.value = false;
    }
};

let parentPageSearchTimer: ReturnType<typeof setTimeout> | undefined;

watch(parentPageSearch, (value) => {
    if (parentPageSearchTimer) clearTimeout(parentPageSearchTimer);
    parentPageSearchTimer = setTimeout(() => {
        if (!dialog.value || entryType.value !== 'sub') return;
        fetchParentPages(value);
    }, 300);
});

watch([dialog, entryType], ([isOpen, type]) => {
    if (!isOpen) {
        parentPageSearch.value = '';
        parentPageItems.value = [];
        parentPageLoading.value = false;
        return;
    }

    if (type === 'sub') {
        fetchParentPages(parentPageSearch.value);
    } else {
        parentModule.value = null;
    }
});

let lastLoadedKey = '';

const fetchPageDetail = async () => {
    if (!props.pageId) return;

    const key = `${props.mode}:${props.pageId}`;
    if (lastLoadedKey === key) return;
    lastLoadedKey = key;

    isLoadingDetail.value = true;
    try {
        const response = await api.get(`/api/v1/roles/pages/${props.pageId}`);
        const data = response.data?.data;
        if (!data) throw new Error('Data menu tidak ditemukan');

        labelName.value = data.name ?? '';
        icon.value = data.icon ?? '';
        url.value = data.url ?? '';
        sortOrder.value = typeof data.sort === 'number' ? data.sort : null;
        active.value = typeof data.active === 'boolean' ? data.active : true;

        const isSub = data.parent != null;
        entryType.value = isSub ? 'sub' : 'main';
        parentModule.value = isSub ? data.parent : null;

        if (isSub) {
            await fetchParentPages('');
        }
    } catch (error: any) {
        const message = error?.response?.data?.message || error?.message || 'Gagal memuat detail menu';
        snackbarStore.showSnackbar(message, 'error');
    } finally {
        isLoadingDetail.value = false;
    }
};

watch(
    [dialog, () => props.mode, () => props.pageId],
    async ([isOpen, mode]) => {
        if (!isOpen) return;

        if (mode === 'create') {
            lastLoadedKey = '';
            resetForm();
            return;
        }

        await fetchPageDetail();
    },
    { immediate: false },
);

const save = () => {
    const run = async () => {
        if (isDetailMode.value) return;
        if (isSaving.value) return;
        isSaving.value = true;

        try {
            await formRef.value?.validate?.();
            if (!valid.value) {
                snackbarStore.showSnackbar('Lengkapi form terlebih dahulu', 'error');
                return;
            }

            const isSubMenu = entryType.value === 'sub';
            const parentId = isSubMenu ? parentModule.value : null;
            let level = 1;

            if (isSubMenu) {
                if (!parentId) {
                    snackbarStore.showSnackbar('Menu induk tidak ditemukan, silakan pilih ulang', 'error');
                    return;
                }

                const parentLevel = await resolveParentLevel(parentId);
                if (parentLevel == null) {
                    snackbarStore.showSnackbar('Menu induk tidak ditemukan, silakan pilih ulang', 'error');
                    return;
                }
                level = parentLevel + 1;
            }

            const payload: Record<string, any> = {
                name: labelName.value,
                icon: icon.value,
                url: url.value,
                level,
                sort: sortOrder.value,
                active: active.value,
            };

            if (isCreateMode.value) {
                if (isSubMenu) payload.parent = parentId;
                await api.post('/api/v1/roles/pages', payload);
                snackbarStore.showSnackbar('Menu berhasil ditambahkan', 'success');
            } else if (isEditMode.value) {
                if (!props.pageId) throw new Error('ID menu tidak ditemukan');
                payload.parent = parentId;
                await api.put(`/api/v1/roles/pages/${props.pageId}`, payload);
                snackbarStore.showSnackbar('Menu berhasil diperbarui', 'success');
            }

            emit('saved');
            close();
        } catch (error: any) {
            const message = error?.response?.data?.message || error?.message || 'Gagal menambahkan menu';
            snackbarStore.showSnackbar(message, 'error');
        } finally {
            isSaving.value = false;
        }
    };

    run();
};

const close = () => {
    emit('update:modelValue', false);
    lastLoadedKey = '';
    resetForm();
};

const resetCurrent = async () => {
    if (isDetailMode.value) return;
    if (isSaving.value || isLoadingDetail.value) return;

    if (isCreateMode.value) {
        resetForm();
        return;
    }

    // For edit mode, restore to the last saved/loaded state
    lastLoadedKey = '';
    await fetchPageDetail();
};
</script>

<template>
    <AppRightDialog v-model="dialog" :max-width="500" persistent>
        <v-card>
            <v-form v-model="valid" ref="formRef" @submit.prevent="save">
            <v-card-title class="d-flex align-center justify-space-between pa-3">
                <div class="d-flex align-center">
                    <span class="ml-3 text-h5">{{ titleText }}</span>
                </div>
                <v-btn
                    icon
                    variant="text"
                    @click="close"
                >
                    <v-icon>mdi-close</v-icon>
                </v-btn>
            </v-card-title>
                <v-divider></v-divider>
                <v-card-text>
                    <div>
                        <label class="font-weight-medium required">Tipe Menu</label>
                        <div class="d-flex gap-2 mt-2 rounded-lg">
                            <v-btn value="main" class="flex-grow-1" @click="entryType = 'main'" color="primary"
                                :readonly="isFormDisabled" :variant="entryType === 'main' ? 'flat' : 'outlined'" height="88" rounded="lg">
                                <div class="d-flex flex-column align-center">
                                    <v-icon class="mb-1">mdi-file-document-outline</v-icon>
                                    <span>Main Menu</span>
                                </div>
                            </v-btn>
                            <v-btn value="sub" class="flex-grow-1" @click="entryType = 'sub'" color="primary"
                                :readonly="isFormDisabled" :variant="entryType === 'sub' ? 'flat' : 'outlined'" height="88" rounded="lg">
                                <div class="d-flex flex-column align-center">
                                    <v-icon class="mb-1">mdi-file-tree-outline</v-icon>
                                    <span>Sub-Menu</span>
                                </div>
                            </v-btn>
                        </div>
                    </div>

                    <div class="mt-2">
                        <label class="font-weight-medium required">Nama Menu</label>
                        <v-text-field v-model="labelName" class="mt-2" variant="outlined" density="compact"
                            :readonly="isFormDisabled" :rules="[required]" />
                    </div>

                    <div v-if="entryType === 'sub'">
                        <label class="font-weight-medium required">Menu Induk</label>
                        <v-autocomplete v-model="parentModule" v-model:search="parentPageSearch" class="mt-2"
                            :items="parentPageItems" item-title="name" item-value="id" placeholder="Pilih menu induk"
                            variant="outlined" density="compact" :readonly="isFormDisabled" :loading="parentPageLoading" no-filter clearable
                            :rules="[required]" />
                    </div>

                    <div>
                        <label class="font-weight-medium required">URL</label>
                        <v-text-field v-model="url" class="mt-2" placeholder="" variant="outlined"
                            density="compact" :readonly="isFormDisabled" :rules="[required]" />
                    </div>

                    <v-row>
                        <v-col cols="6">
                            <label class="font-weight-medium required">Urutan</label>
                            <v-text-field v-model.number="sortOrder" class="mt-2" type="number" placeholder="urutan menu"
                                variant="outlined" density="compact" :readonly="isFormDisabled" :rules="[required, isNumber]" />
                        </v-col>
                        <v-col cols="6">
                            <label class="font-weight-medium required">Menu Icon</label>
                            <v-text-field v-model="icon" class="mt-2" placeholder="icon menu" variant="outlined"
                                density="compact" :readonly="isFormDisabled" :rules="[required]">
                                <template #append-inner>
                                    <!-- <v-avatar color="primary"  size="32"> -->
                                    <Icon v-if="icon" class="text-primary" :icon="'solar:' + icon" width="20" />
                                    <!-- </v-avatar> -->
                                </template>
                            </v-text-field>
                        </v-col>
                    </v-row>

                    <div>
                        <label class="font-weight-medium required">Status</label>
                        <v-switch v-model="active" class="mt-2" color="primary" inset :readonly="isFormDisabled" hide-details>
                            <template #label>
                                <span>{{ active ? 'Aktif' : 'Nonaktif' }}</span>
                            </template>
                        </v-switch>
                    </div>
                </v-card-text>
                <v-divider></v-divider>
                <v-card-actions class="pa-4">
                    <v-row v-if="!isDetailMode" class="w-100" dense>
                        <v-col cols="6">
                            <v-btn
                                prepend-icon="mdi-refresh"
                                class="w-100"
                                type="button"
                                color="default"
                                variant="outlined"
                                :disabled="isFormDisabled"
                                @click="resetCurrent"
                            >
                                Reset
                            </v-btn>
                        </v-col>
                        <v-col cols="6">
                            <v-btn
                                prepend-icon="mdi-content-save"
                                class="w-100"
                                color="primary"
                                type="submit"
                                variant="flat"
                                :loading="isSaving"
                                :disabled="isFormDisabled"
                            >
                                {{ submitLabel }}
                            </v-btn>
                        </v-col>
                    </v-row>
                </v-card-actions>
            </v-form>
        </v-card>
    </AppRightDialog>
</template>
