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

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

const emit = defineEmits<{
	(e: 'update:modelValue', value: boolean): void;
	(e: 'saved'): void;
}>();

const dialog = ref(props.modelValue);

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

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

const snackbarStore = useSnackbarStore();
const { required } = useValidation();

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

const name = ref('');
const slug = 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 Role';
	if (isEditMode.value) return 'Edit Role';
	return 'Detail Role';
});

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

const resetForm = () => {
	name.value = '';
	slug.value = '';
	active.value = true;
	valid.value = false;
	formRef.value?.resetValidation?.();
};

let lastLoadedKey = '';

const fetchRoleDetail = async () => {
	if (!props.roleId) return;

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

	isLoadingDetail.value = true;
	try {
		const response = await api.get<RoleMasterResponse>(`/api/v1/roles/master/${props.roleId}`);
		const data: RoleMaster | undefined = response.data?.data;
		if (!data) throw new Error('Data role tidak ditemukan');

		name.value = data.name ?? '';
		slug.value = data.slug ?? '';
		active.value = typeof data.active === 'boolean' ? data.active : true;
	} catch (error: any) {
		const message = error?.response?.data?.message || error?.message || 'Gagal memuat detail role';
		snackbarStore.showSnackbar(message, 'error');
	} finally {
		isLoadingDetail.value = false;
	}
};

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

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

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

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

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 payload: Record<string, any> = {
				name: name.value,
				slug: slug.value,
				active: active.value,
			};

			if (isCreateMode.value) {
				await api.post('/api/v1/roles/master', payload);
				snackbarStore.showSnackbar('Role berhasil ditambahkan', 'success');
			} else if (isEditMode.value) {
				if (!props.roleId) throw new Error('ID role tidak ditemukan');
				await api.put(`/api/v1/roles/master/${props.roleId}`, payload);
				snackbarStore.showSnackbar('Role berhasil diperbarui', 'success');
			}

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

	run();
};
</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">
					<span class="ml-3 text-h6">{{ titleText }}</span>
					<v-btn icon variant="text" @click="close">
						<v-icon>mdi-close</v-icon>
					</v-btn>
				</v-card-title>

				<v-divider />

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

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

					<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-card-actions class="pa-4">
					<v-spacer />
					<v-btn v-if="!isDetailMode" class="w-50" color="primary" type="submit" variant="flat" :loading="isSaving" :disabled="isSaving">
						{{ submitLabel }}
					</v-btn>
				</v-card-actions>
			</v-form>
		</v-card>
	</AppRightDialog>
</template>
