<script setup lang="ts">
/* eslint-disable vue/no-mutating-props -- Inertia useForm objects are reactive and designed to be mutated via props */
import type { Form } from '@inertiajs/vue3';
import InputError from '@/components/InputError.vue';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';

export type WorkspaceFormData = {
    name: string;
    slug: string;
    user_ids: number[];
    user_roles: Record<number, string>;
};

export type WorkspaceFormUser = {
    id: number;
    name: string;
    email: string;
};

type Props = {
    form: Form<WorkspaceFormData>;
    users: WorkspaceFormUser[];
    workspaceUserRoles: Record<string, string>;
    submitLabel?: string;
};

const props = withDefaults(defineProps<Props>(), {
    submitLabel: 'Save',
});

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

const defaultRole = 'worker';

function onUserToggle(userId: number, checked: boolean) {
    if (checked) {
        const ids = props.form.user_ids ?? [];
        if (!ids.includes(userId)) {
            props.form.user_ids = [...ids, userId];
        }
        const roles = props.form.user_roles ?? {};
        props.form.user_roles = {
            ...roles,
            [userId]: roles[userId] ?? defaultRole,
        };
    } else {
        props.form.user_ids = (props.form.user_ids ?? []).filter(
            (id) => id !== userId,
        );
        const roles = { ...(props.form.user_roles ?? {}) };
        delete roles[userId];
        props.form.user_roles = roles;
    }
}

function onRoleChange(userId: number, role: string) {
    const roles = props.form.user_roles ?? {};
    props.form.user_roles = { ...roles, [userId]: role };
}

function isUserSelected(userId: number): boolean {
    return (props.form.user_ids ?? []).includes(userId);
}

function getUserRole(userId: number): string {
    return props.form.user_roles?.[userId] ?? defaultRole;
}
</script>

<template>
    <form @submit.prevent="emit('submit')" class="flex flex-col space-y-6">
        <div class="grid gap-2">
            <Label for="name">Name</Label>
            <Input
                id="name"
                v-model="form.name"
                type="text"
                required
                placeholder="Cabinet Comptable XYZ"
                aria-invalid="!!form.errors.name"
            />
            <InputError :message="form.errors.name" />
        </div>

        <div class="grid gap-2">
            <Label for="slug">Slug</Label>
            <Input
                id="slug"
                v-model="form.slug"
                type="text"
                placeholder="cabinet-comptable-xyz (optional)"
                aria-invalid="!!form.errors.slug"
            />
            <p class="text-xs text-muted-foreground">
                Leave empty to auto-generate from the name.
            </p>
            <InputError :message="form.errors.slug" />
        </div>

        <div v-if="users?.length" class="grid gap-2">
            <Label>Users</Label>
            <p class="text-xs text-muted-foreground">
                Select users to add to this workspace.
            </p>
            <div
                class="max-h-48 space-y-2 overflow-y-auto rounded-md border border-sidebar-border/70 p-3 dark:border-sidebar-border"
            >
                <div
                    v-for="user in users"
                    :key="user.id"
                    class="flex items-center gap-3 rounded px-2 py-1.5 hover:bg-muted/50"
                >
                    <input
                        type="checkbox"
                        :value="user.id"
                        :checked="isUserSelected(user.id)"
                        class="size-4 shrink-0 rounded-[4px] border border-input focus-visible:ring-2 focus-visible:ring-ring"
                        @change="
                            onUserToggle(
                                user.id,
                                ($event.target as HTMLInputElement).checked,
                            )
                        "
                    />
                    <div class="flex min-w-0 flex-1 flex-col">
                        <span class="text-sm font-medium">{{ user.name }}</span>
                        <span class="text-xs text-muted-foreground">{{
                            user.email
                        }}</span>
                    </div>
                    <select
                        :value="getUserRole(user.id)"
                        :disabled="!isUserSelected(user.id)"
                        class="h-8 shrink-0 rounded-md border border-input bg-background px-2 text-sm disabled:opacity-50"
                        @change="
                            onRoleChange(
                                user.id,
                                ($event.target as HTMLSelectElement).value,
                            )
                        "
                    >
                        <option
                            v-for="(label, value) in workspaceUserRoles"
                            :key="value"
                            :value="value"
                        >
                            {{ label }}
                        </option>
                    </select>
                </div>
            </div>
            <InputError :message="form.errors.user_ids" />
        </div>

        <div class="flex items-center gap-4">
            <Button
                type="submit"
                :disabled="form.processing"
                data-test="workspace-form-submit"
            >
                <Spinner v-if="form.processing" />
                {{ submitLabel }}
            </Button>
        </div>
    </form>
</template>
