<script setup lang="ts">
import { Accordion } from '@/components/ui/accordion';
import {
    AlertDialog,
    AlertDialogAction,
    AlertDialogCancel,
    AlertDialogContent,
    AlertDialogDescription,
    AlertDialogFooter,
    AlertDialogHeader,
    AlertDialogTitle,
    AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { useForm } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/yup';
import { editUserSchema } from '~/lib/schemas/admin';
import { editUser } from '~/lib/api/admin/editUser';
import type { AuthUserWithWarrens } from '~/shared/types/admin';

const adminStore = useAdminStore();

const isValid = computed(() => Object.keys(form.errors.value).length < 1);

// We'll only update this value if there is a user to prevent layout shifts on close
const user = ref<AuthUserWithWarrens>();
const editing = ref(false);

const isChanged = computed(() => {
    if (user.value == null) {
        return false;
    }

    try {
        const values = editUserSchema.validateSync(form.controlledValues.value);
        return (
            values.name !== user.value.name ||
            values.email !== user.value.email ||
            values.password != null ||
            values.admin !== user.value.admin
        );
    } catch {
        return true;
    }
});

function close() {
    adminStore.closeEditUserDialog();
}

const form = useForm({
    validationSchema: toTypedSchema(editUserSchema),
});

adminStore.$subscribe((_mutation, state) => {
    if (state.editUserDialog != null && !editing.value) {
        user.value = state.resources.users.find(
            (u) => u.id === state.editUserDialog?.user.id
        );

        if (user.value != null) {
            form.setValues(user.value);
        }
    }
});

const onSubmit = form.handleSubmit(async (values) => {
    if (user.value == null || !isChanged.value || editing.value) {
        return;
    }

    editing.value = true;

    const result = await editUser({
        id: user.value.id,
        name: values.name,
        email: values.email,
        password: values.password ?? null,
        admin: values.admin,
    });

    if (result.success) {
        const newUser: AuthUserWithWarrens = {
            id: result.user.id,
            name: result.user.name,
            email: result.user.email,
            admin: result.user.admin,
            warrens: user.value.warrens,
        };
        adminStore.setEditUserDialog(newUser);
    }

    editing.value = false;
});
</script>

<template>
    <AlertDialog :open="adminStore.editUserDialog != null">
        <AlertDialogTrigger><slot /></AlertDialogTrigger>
        <AlertDialogContent
            v-if="user != null"
            class="flex max-h-[95vh] flex-col"
            @escape-key-down="close"
        >
            <AlertDialogHeader class="shrink">
                <AlertDialogTitle>Edit user</AlertDialogTitle>
                <AlertDialogDescription>
                    Modify the user's fields, manage permissions or assign
                    warrens
                </AlertDialogDescription>
            </AlertDialogHeader>

            <ScrollArea
                class="flex h-full grow flex-col justify-start overflow-hidden"
            >
                <form
                    id="edit-user-form"
                    class="flex flex-col gap-2"
                    @submit.prevent="onSubmit"
                >
                    <FormField v-slot="{ componentField }" name="name">
                        <FormItem>
                            <FormLabel>Username</FormLabel>
                            <FormControl>
                                <Input
                                    v-bind="componentField"
                                    id="username"
                                    type="text"
                                    placeholder="confused-cat"
                                    autocomplete="off"
                                    data-1p-ignore
                                    data-protonpass-ignore
                                    data-bwignore
                                />
                            </FormControl>
                            <FormMessage />
                        </FormItem>
                    </FormField>

                    <FormField v-slot="{ componentField }" name="email">
                        <FormItem>
                            <FormLabel>Email</FormLabel>
                            <FormControl>
                                <Input
                                    v-bind="componentField"
                                    id="email"
                                    type="email"
                                    placeholder="confusedcat@example.com"
                                    autocomplete="off"
                                    data-1p-ignore
                                    data-protonpass-ignore
                                    data-bwignore
                                />
                            </FormControl>
                            <FormMessage />
                        </FormItem>
                    </FormField>

                    <FormField v-slot="{ componentField }" name="password">
                        <FormItem>
                            <FormLabel>Password</FormLabel>
                            <FormControl>
                                <Input
                                    v-bind="componentField"
                                    id="password"
                                    type="password"
                                    autocomplete="off"
                                    data-1p-ignore
                                    data-protonpass-ignore
                                    data-bwignore
                                />
                            </FormControl>
                            <FormMessage />
                            <FormDescription
                                >Leave empty to keep the current
                                password</FormDescription
                            >
                        </FormItem>
                    </FormField>

                    <FormField v-slot="{ value, handleChange }" name="admin">
                        <FormItem>
                            <FormLabel>Admin</FormLabel>
                            <FormControl>
                                <Switch
                                    id="admin"
                                    :model-value="value"
                                    @update:model-value="handleChange"
                                />
                            </FormControl>
                            <FormMessage />
                        </FormItem>
                    </FormField>

                    <AlertDialogAction
                        type="submit"
                        form="edit-user-form"
                        :disabled="!isChanged || !isValid"
                        >Save</AlertDialogAction
                    >
                </form>

                <Separator orientation="horizontal" class="my-4" />

                <div class="flex w-full flex-col gap-2">
                    <AdminAddUserWarrenDialog :user>
                        <Button variant="outline" size="icon">
                            <Icon name="lucide:folder-plus" />
                        </Button>
                    </AdminAddUserWarrenDialog>

                    <Accordion
                        v-if="user.warrens.length > 0"
                        class="flex w-full flex-col gap-2"
                        collapsible
                        type="single"
                    >
                        <AdminUserWarrenListing
                            v-for="warren in user.warrens"
                            :key="warren.warrenId"
                            :user-warren="warren"
                        />
                    </Accordion>
                    <div v-else class="flex flex-col gap-4">
                        <span class="text-muted-foreground"
                            >This user is not assigned to any warrens</span
                        >
                    </div>
                </div>
                <Separator orientation="horizontal" class="mt-4" />
            </ScrollArea>

            <AlertDialogFooter class="gap-y-0">
                <AlertDialogCancel @click="close">Close</AlertDialogCancel>
            </AlertDialogFooter>
        </AlertDialogContent>
    </AlertDialog>
</template>
