import { Head, Link, router, useForm, usePage } from '@inertiajs/react';
import type { FormEvent } from 'react';
import { useMemo, useRef, useState } from 'react';
import '../../../css/access-management.css';

type PermissionValue = boolean | null;

type PermissionDefinition = {
    key: string;
    label: string;
    description: string;
    group: string;
};

type RoleValue = 'administrator' | 'couple' | 'helper' | 'guest';

type RoleDefinition = {
    value: RoleValue;
    label: string;
    description: string;
    permissions: string[];
    isAssignable: boolean;
};

type Membership = {
    id: string;
    userId: number;
    name: string;
    email: string;
    role: RoleValue;
    isActive: boolean;
    permissionOverrides: Record<string, PermissionValue>;
};

type GuestTag = {
    id: string;
    name: string;
    color: string;
    guestCount: number;
};

type Guest = {
    id: string;
    name: string;
    groupLabel: string;
    isChild: boolean;
    tagIds: string[];
};

type PageProps = {
    wedding: { name: string };
    permissions: PermissionDefinition[];
    roles: RoleDefinition[];
    memberships: Membership[];
    tags: GuestTag[];
    guests: Guest[];
    flash: { success: string | null };
    errors: Record<string, string>;
};

type MembershipForm = {
    role: RoleValue;
    is_active: boolean;
    permission_overrides: Record<string, PermissionValue>;
};

type TagForm = {
    name: string;
    color: string;
};

type ActiveArea = 'roles' | 'tags';
type MembershipStatusFilter = 'all' | 'active' | 'inactive';

const DEFAULT_COLOR = '#879b82';
const HEX_COLOR = /^#[0-9a-fA-F]{6}$/;

const normalize = (value: string) => value.trim().toLocaleLowerCase('de-DE');

const roleFallback: RoleValue = 'guest';

export default function AccessIndex() {
    const { wedding, permissions, roles, memberships, tags, guests, flash, errors } = usePage<PageProps>().props;
    const [activeArea, setActiveArea] = useState<ActiveArea>('roles');
    const [memberSearch, setMemberSearch] = useState('');
    const [roleFilter, setRoleFilter] = useState<'all' | RoleValue>('all');
    const [statusFilter, setStatusFilter] = useState<MembershipStatusFilter>('all');
    const [editingMembershipId, setEditingMembershipId] = useState<string | null>(null);
    const [tagSearch, setTagSearch] = useState('');
    const [tagFilter, setTagFilter] = useState('all');
    const [editingTagId, setEditingTagId] = useState<string | null>(null);
    const [colorError, setColorError] = useState<string | null>(null);
    const [pendingTagAction, setPendingTagAction] = useState<string | null>(null);
    const [pendingGuestId, setPendingGuestId] = useState<string | null>(null);
    const [guestErrorOwner, setGuestErrorOwner] = useState<string | null>(null);
    const [guestTagDrafts, setGuestTagDrafts] = useState<Record<string, string[]>>(() =>
        Object.fromEntries(guests.map((guest) => [guest.id, [...guest.tagIds]])),
    );
    const memberEditorHeading = useRef<HTMLHeadingElement>(null);
    const tagEditorHeading = useRef<HTMLHeadingElement>(null);

    const membershipForm = useForm<MembershipForm>({
        role: roles[0]?.value ?? roleFallback,
        is_active: true,
        permission_overrides: {},
    });
    const tagForm = useForm<TagForm>({ name: '', color: DEFAULT_COLOR });

    const filteredMemberships = useMemo(() => {
        const query = normalize(memberSearch);
        return memberships.filter((membership) => {
            const matchesSearch = !query
                || normalize(membership.name).includes(query)
                || normalize(membership.email).includes(query);
            const matchesRole = roleFilter === 'all' || membership.role === roleFilter;
            const matchesStatus = statusFilter === 'all'
                || (statusFilter === 'active' ? membership.isActive : !membership.isActive);
            return matchesSearch && matchesRole && matchesStatus;
        });
    }, [memberSearch, memberships, roleFilter, statusFilter]);

    const filteredGuests = useMemo(() => {
        const query = normalize(tagSearch);
        return guests.filter((guest) => {
            const matchesSearch = !query
                || normalize(guest.name).includes(query)
                || normalize(guest.groupLabel).includes(query);
            const matchesTag = tagFilter === 'all' || (guestTagDrafts[guest.id] ?? guest.tagIds).includes(tagFilter);
            return matchesSearch && matchesTag;
        });
    }, [guestTagDrafts, guests, tagFilter, tagSearch]);

    const permissionsByGroup = useMemo(() => {
        const groups = new Map<string, PermissionDefinition[]>();
        permissions.forEach((permission) => {
            groups.set(permission.group, [...(groups.get(permission.group) ?? []), permission]);
        });
        return [...groups.entries()];
    }, [permissions]);

    const selectedRole = roles.find((role) => role.value === membershipForm.data.role);
    const editingMembership = memberships.find((membership) => membership.id === editingMembershipId) ?? null;
    const validTagColor = HEX_COLOR.test(tagForm.data.color);
    const generalError = errors.access ?? errors.membership ?? errors.tag ?? errors.guest ?? errors.general;
    const guestTagErrors = [...new Set(Object.entries(errors)
        .filter(([key]) => key === 'tag_ids' || key.startsWith('tag_ids.'))
        .map(([, message]) => message)
        .filter(Boolean))];

    const focusAfterRender = (target: React.RefObject<HTMLElement | null>) => {
        window.setTimeout(() => target.current?.focus(), 100);
    };

    const startMembershipEdit = (membership: Membership) => {
        setEditingMembershipId(membership.id);
        membershipForm.clearErrors();
        membershipForm.setData({
            role: membership.role,
            is_active: membership.isActive,
            permission_overrides: { ...membership.permissionOverrides },
        });
        focusAfterRender(memberEditorHeading);
    };

    const cancelMembershipEdit = () => {
        setEditingMembershipId(null);
        membershipForm.clearErrors();
        membershipForm.reset();
    };

    const setPermissionOverride = (permissionKey: string, value: PermissionValue) => {
        membershipForm.setData('permission_overrides', {
            ...membershipForm.data.permission_overrides,
            [permissionKey]: value,
        });
    };

    const submitMembership = (submitEvent: FormEvent<HTMLFormElement>) => {
        submitEvent.preventDefault();
        if (!editingMembershipId || membershipForm.processing) return;

        membershipForm.transform((data) => ({
            ...data,
            permission_overrides: data.role === 'administrator' ? {} : data.permission_overrides,
        }));
        membershipForm.put(`/zugriffsverwaltung/mitglieder/${editingMembershipId}`, {
            preserveScroll: true,
            onSuccess: () => setEditingMembershipId(null),
        });
    };

    const startTagCreation = () => {
        setEditingTagId(null);
        setColorError(null);
        tagForm.clearErrors();
        tagForm.setData({ name: '', color: DEFAULT_COLOR });
        focusAfterRender(tagEditorHeading);
    };

    const startTagEdit = (tag: GuestTag) => {
        setEditingTagId(tag.id);
        setColorError(null);
        tagForm.clearErrors();
        tagForm.setData({ name: tag.name, color: tag.color });
        focusAfterRender(tagEditorHeading);
    };

    const cancelTagEdit = () => {
        setEditingTagId(null);
        setColorError(null);
        tagForm.clearErrors();
        tagForm.setData({ name: '', color: DEFAULT_COLOR });
    };

    const submitTag = (submitEvent: FormEvent<HTMLFormElement>) => {
        submitEvent.preventDefault();
        if (tagForm.processing) return;
        if (!HEX_COLOR.test(tagForm.data.color)) {
            setColorError('Bitte gib eine Farbe im Format #879b82 ein.');
            return;
        }

        setColorError(null);
        const options = {
            preserveScroll: true,
            onSuccess: () => {
                setEditingTagId(null);
                tagForm.setData({ name: '', color: DEFAULT_COLOR });
            },
        };
        if (editingTagId === null) {
            tagForm.post('/zugriffsverwaltung/tags', options);
        } else {
            tagForm.put(`/zugriffsverwaltung/tags/${editingTagId}`, options);
        }
    };

    const deleteTag = (tag: GuestTag) => {
        if (pendingTagAction || tagForm.processing) return;
        const message = tag.guestCount > 0
            ? `„${tag.name}“ ist ${tag.guestCount} Gästen zugeordnet. Möchtest du die Löschung trotzdem anfragen? Der Server kann sie ablehnen.`
            : `Möchtest du den Tag „${tag.name}“ wirklich löschen?`;
        if (!window.confirm(message)) return;

        setPendingTagAction(tag.id);
        router.delete(`/zugriffsverwaltung/tags/${tag.id}`, {
            preserveScroll: true,
            onSuccess: () => {
                setGuestTagDrafts((drafts) => Object.fromEntries(
                    Object.entries(drafts).map(([guestId, tagIds]) => [guestId, tagIds.filter((tagId) => tagId !== tag.id)]),
                ));
                if (tagFilter === tag.id) setTagFilter('all');
                if (editingTagId === tag.id) cancelTagEdit();
            },
            onFinish: () => setPendingTagAction(null),
        });
    };

    const toggleGuestTag = (guest: Guest, tagId: string, checked: boolean) => {
        const currentTags = guestTagDrafts[guest.id] ?? guest.tagIds;
        const nextTags = checked
            ? [...new Set([...currentTags, tagId])]
            : currentTags.filter((currentTagId) => currentTagId !== tagId);
        setGuestTagDrafts((drafts) => ({ ...drafts, [guest.id]: nextTags }));
    };

    const saveGuestTags = (guest: Guest) => {
        if (pendingGuestId !== null) return;
        setPendingGuestId(guest.id);
        setGuestErrorOwner(guest.id);
        router.put(`/zugriffsverwaltung/gaeste/${guest.id}/tags`, {
            tag_ids: guestTagDrafts[guest.id] ?? guest.tagIds,
        }, {
            preserveScroll: true,
            onSuccess: () => setGuestErrorOwner(null),
            onFinish: () => setPendingGuestId(null),
        });
    };

    return (
        <>
            <Head title="Rollen & Tags" />
            <main className="access-shell">
                <nav className="access-nav" aria-label="Bereichsnavigation">
                    <div><span className="access-eyebrow">{wedding.name}</span><strong>Zugriffsverwaltung</strong></div>
                    <Link className="access-secondary-button" href="/dashboard">Zurück zum Dashboard</Link>
                </nav>

                <header className="access-header">
                    <div><span className="access-eyebrow">Sicher zusammenarbeiten</span><h1>Rollen &amp; Tags</h1></div>
                    <p>Rollen bestimmen den grundsätzlichen Zugriff. Individuelle Einstellungen ergänzen oder entziehen einzelne Rechte als gezielte Ausnahme.</p>
                </header>

                {flash.success && <div className="alert access-success" role="status">{flash.success}</div>}
                {generalError && <div className="alert alert-danger access-page-alert" role="alert">{generalError}</div>}

                <div className="access-tabs" aria-label="Verwaltungsbereich wählen" role="tablist">
                    <button aria-controls="access-roles-panel" aria-selected={activeArea === 'roles'} className={activeArea === 'roles' ? 'is-active' : ''} id="access-roles-tab" onClick={() => setActiveArea('roles')} role="tab" type="button">Rollen &amp; Berechtigungen</button>
                    <button aria-controls="access-tags-panel" aria-selected={activeArea === 'tags'} className={activeArea === 'tags' ? 'is-active' : ''} id="access-tags-tab" onClick={() => setActiveArea('tags')} role="tab" type="button">Gäste-Tags</button>
                </div>

                {activeArea === 'roles' ? (
                    <div aria-labelledby="access-roles-tab" className="access-role-layout" id="access-roles-panel" role="tabpanel">
                        <section className="access-panel" aria-labelledby="memberships-title">
                            <div className="access-section-heading"><div><span className="access-eyebrow">Mitglieder</span><h2 id="memberships-title">Rollen verwalten</h2></div><span className="access-count">{memberships.length}</span></div>
                            <div className="access-member-filters">
                                <div className="access-search-field"><label htmlFor="member-search">Name oder E-Mail suchen</label><input id="member-search" onChange={(e) => setMemberSearch(e.target.value)} placeholder="Mitglied suchen …" type="search" value={memberSearch} /></div>
                                <div><label htmlFor="member-role-filter">Rolle</label><select className="form-select" id="member-role-filter" onChange={(e) => setRoleFilter(e.target.value as 'all' | RoleValue)} value={roleFilter}><option value="all">Alle Rollen</option>{roles.map((role) => <option key={role.value} value={role.value}>{role.label}</option>)}</select></div>
                                <div><label htmlFor="member-status-filter">Status</label><select className="form-select" id="member-status-filter" onChange={(e) => setStatusFilter(e.target.value as MembershipStatusFilter)} value={statusFilter}><option value="all">Alle</option><option value="active">Aktiv</option><option value="inactive">Inaktiv</option></select></div>
                            </div>

                            {memberships.length === 0 ? <div className="access-empty"><span aria-hidden="true">◇</span><h3>Noch keine Mitgliedschaften</h3><p>Sobald Mitglieder verfügbar sind, können ihre Rollen hier verwaltet werden.</p></div>
                                : filteredMemberships.length === 0 ? <div className="access-empty is-compact"><h3>Keine passenden Mitglieder</h3><p>Ändere die Suche oder einen der Filter.</p></div>
                                    : <div className="access-member-list">{filteredMemberships.map((membership) => {
                                        const role = roles.find((item) => item.value === membership.role);
                                        return <article className={`access-member-card${editingMembershipId === membership.id ? ' is-editing' : ''}`} key={membership.id}>
                                            <div className="access-member-avatar" aria-hidden="true">{membership.name.trim().charAt(0).toUpperCase() || '◇'}</div>
                                            <div className="access-member-copy"><h3>{membership.name}</h3><p>{membership.email}</p><div><span>{role?.label ?? membership.role}</span><span className={membership.isActive ? 'is-active' : 'is-inactive'}>{membership.isActive ? 'Aktiv' : 'Inaktiv'}</span></div></div>
                                            <button aria-label={`${membership.name} bearbeiten`} className="access-text-button" disabled={membershipForm.processing} onClick={() => startMembershipEdit(membership)} type="button">Bearbeiten</button>
                                        </article>;
                                    })}</div>}
                        </section>

                        <aside className="access-panel access-member-editor" aria-labelledby="member-editor-title">
                            <div className="access-section-heading"><div><span className="access-eyebrow">Einstellungen</span><h2 id="member-editor-title" ref={memberEditorHeading} tabIndex={-1}>{editingMembership ? editingMembership.name : 'Mitglied auswählen'}</h2></div>{editingMembership && <button className="access-text-button" onClick={cancelMembershipEdit} type="button">Abbrechen</button>}</div>
                            {!editingMembership ? <div className="access-editor-placeholder"><span aria-hidden="true">◇</span><p>Wähle ein Mitglied aus, um Rolle, Status und individuelle Berechtigungen zu bearbeiten.</p></div> : (
                                <form aria-busy={membershipForm.processing} noValidate onSubmit={submitMembership}>
                                    <p className="access-editor-email">{editingMembership.email}</p>
                                    <div className="mb-3"><label className="form-label" htmlFor="membership-role">Rolle</label><select className={`form-select${membershipForm.errors.role ? ' is-invalid' : ''}`} disabled={membershipForm.processing} id="membership-role" onChange={(e) => membershipForm.setData('role', e.target.value as RoleValue)} value={membershipForm.data.role}>{roles.map((role) => <option disabled={!role.isAssignable} key={role.value} value={role.value}>{role.label}{!role.isAssignable ? ' · nicht zuweisbar' : ''}</option>)}</select>{membershipForm.errors.role && <div className="invalid-feedback">{membershipForm.errors.role}</div>}{selectedRole && <small className="access-role-description">{selectedRole.description}</small>}</div>
                                    <label className="access-active-toggle"><input checked={membershipForm.data.is_active} className="form-check-input" disabled={membershipForm.processing} onChange={(e) => membershipForm.setData('is_active', e.target.checked)} type="checkbox" /><span><strong>Mitgliedschaft aktiv</strong><small>Inaktive Mitglieder erhalten keinen Zugriff.</small></span></label>
                                    {membershipForm.errors.is_active && <div className="access-field-error">{membershipForm.errors.is_active}</div>}

                                    {membershipForm.data.role === 'administrator' ? <div className="access-admin-note"><strong>Uneingeschränkte Administration</strong><p>Für Administratoren werden keine individuellen Einschränkungen angeboten.</p></div> : (
                                        <div className="access-permissions"><div className="access-permissions-intro"><h3>Individuelle Berechtigungen</h3><p>„Rollenstandard“ übernimmt die Vorgabe der ausgewählten Rolle.</p></div>{permissionsByGroup.map(([groupName, groupPermissions]) => <section key={groupName}><h4>{groupName}</h4><div>{groupPermissions.map((permission) => {
                                            const roleIncludesPermission = selectedRole?.permissions.includes(permission.key) ?? false;
                                            const override = membershipForm.data.permission_overrides[permission.key] ?? null;
                                            const error = (membershipForm.errors as Record<string, string>)[`permission_overrides.${permission.key}`];
                                            return <fieldset className="access-permission-card" key={permission.key}><legend>{permission.label}</legend><p>{permission.description}</p><span className={`access-role-default${roleIncludesPermission ? ' is-included' : ''}`}>Rollenstandard: {roleIncludesPermission ? 'erlaubt' : 'nicht enthalten'}</span><div className="access-override-options">{([{ value: 'default', label: 'Rollenstandard', payload: null }, { value: 'allow', label: 'Ausdrücklich erlauben', payload: true }, { value: 'deny', label: 'Ausdrücklich entziehen', payload: false }] as const).map((choice) => { const inputId = `permission-${editingMembership.id}-${permission.key}-${choice.value}`; return <label htmlFor={inputId} key={choice.value}><input checked={override === choice.payload} className="form-check-input" id={inputId} name={`permission-${permission.key}`} onChange={() => setPermissionOverride(permission.key, choice.payload)} type="radio" /><span>{choice.label}</span></label>; })}</div>{error && <div className="access-field-error" role="alert">{error}</div>}</fieldset>;
                                        })}</div></section>)}</div>
                                    )}
                                    <button className="access-primary-button" disabled={membershipForm.processing} type="submit">{membershipForm.processing ? 'Wird gespeichert …' : 'Änderungen speichern'}</button>
                                </form>
                            )}
                        </aside>
                    </div>
                ) : (
                    <div aria-labelledby="access-tags-tab" className="access-tags-area" id="access-tags-panel" role="tabpanel">
                        <div className="access-tag-top-grid">
                            <section className="access-panel" aria-labelledby="tags-title"><div className="access-section-heading"><div><span className="access-eyebrow">Organisation</span><h2 id="tags-title">Vorhandene Tags</h2></div><span className="access-count">{tags.length}</span></div>
                                {tags.length === 0 ? <div className="access-empty"><span aria-hidden="true">◇</span><h3>Noch keine Tags</h3><p>Erstelle einen Tag, um Gäste flexibel zu gruppieren.</p></div> : <div className="access-tag-list">{tags.map((tag) => <article className={`access-tag-card${editingTagId === tag.id ? ' is-editing' : ''}`} key={tag.id}><span className="access-color-dot" style={{ backgroundColor: HEX_COLOR.test(tag.color) ? tag.color : DEFAULT_COLOR }} /><div><h3>{tag.name}</h3><p>{tag.guestCount} {tag.guestCount === 1 ? 'Gast' : 'Gäste'}</p>{tag.guestCount > 0 && <small>Zuordnungen können vom Löschen betroffen sein.</small>}</div><div><button className="access-text-button" disabled={Boolean(pendingTagAction) || tagForm.processing} onClick={() => startTagEdit(tag)} type="button">Bearbeiten</button><button className="access-text-button is-danger" disabled={Boolean(pendingTagAction) || tagForm.processing} onClick={() => deleteTag(tag)} type="button">{pendingTagAction === tag.id ? 'Wird gelöscht …' : 'Löschen'}</button></div></article>)}</div>}
                            </section>

                            <aside className="access-panel access-tag-editor" aria-labelledby="tag-editor-title"><div className="access-section-heading"><div><span className="access-eyebrow">{editingTagId ? 'Tag bearbeiten' : 'Neuer Tag'}</span><h2 id="tag-editor-title" ref={tagEditorHeading} tabIndex={-1}>{editingTagId ? 'Details ändern' : 'Tag erstellen'}</h2></div>{editingTagId && <button className="access-text-button" onClick={cancelTagEdit} type="button">Abbrechen</button>}</div>
                                <form aria-busy={tagForm.processing} noValidate onSubmit={submitTag}><div className="mb-3"><label className="form-label" htmlFor="tag-name">Name</label><input className={`form-control${tagForm.errors.name ? ' is-invalid' : ''}`} id="tag-name" onChange={(e) => tagForm.setData('name', e.target.value)} placeholder="z. B. Trauzeugen" value={tagForm.data.name} />{tagForm.errors.name && <div className="invalid-feedback">{tagForm.errors.name}</div>}</div><fieldset className="access-color-fields"><legend>Farbe</legend><label><span className="visually-hidden">Farbe auswählen</span><input aria-label="Farbe auswählen" disabled={tagForm.processing} onChange={(e) => { setColorError(null); tagForm.setData('color', e.target.value); }} type="color" value={validTagColor ? tagForm.data.color : DEFAULT_COLOR} /></label><div><label className="visually-hidden" htmlFor="tag-color-text">Hex-Farbwert</label><input aria-invalid={Boolean(colorError || tagForm.errors.color)} className={`form-control${colorError || tagForm.errors.color ? ' is-invalid' : ''}`} id="tag-color-text" onChange={(e) => { setColorError(null); tagForm.setData('color', e.target.value); }} placeholder="#879b82" value={tagForm.data.color} />{(colorError || tagForm.errors.color) && <div className="invalid-feedback">{colorError || tagForm.errors.color}</div>}</div><span className="access-color-preview" style={{ backgroundColor: validTagColor ? tagForm.data.color : 'transparent' }} aria-label={validTagColor ? `Farbvorschau ${tagForm.data.color}` : 'Keine gültige Farbvorschau'} /></fieldset><button className="access-primary-button" disabled={tagForm.processing || Boolean(pendingTagAction)} type="submit">{tagForm.processing ? 'Wird gespeichert …' : editingTagId ? 'Tag speichern' : 'Tag erstellen'}</button></form>
                            </aside>
                        </div>

                        <section className="access-panel access-guests-panel" aria-labelledby="guest-tags-title"><div className="access-section-heading"><div><span className="access-eyebrow">Zuordnung</span><h2 id="guest-tags-title">Tags pro Gast</h2></div><span className="access-count">{guests.length}</span></div><div className="access-guest-filters"><div className="access-search-field"><label htmlFor="guest-search">Gast oder Einladungsgruppe suchen</label><input id="guest-search" onChange={(e) => setTagSearch(e.target.value)} placeholder="Gast suchen …" type="search" value={tagSearch} /></div><div><label htmlFor="guest-tag-filter">Nach Tag filtern</label><select className="form-select" disabled={tags.length === 0} id="guest-tag-filter" onChange={(e) => setTagFilter(e.target.value)} value={tagFilter}><option value="all">Alle Tags</option>{tags.map((tag) => <option key={tag.id} value={tag.id}>{tag.name}</option>)}</select></div></div>
                            {guests.length === 0 ? <div className="access-empty"><span aria-hidden="true">◇</span><h3>Noch keine Gäste</h3><p>Sobald Gäste vorhanden sind, können ihnen hier Tags zugewiesen werden.</p></div> : filteredGuests.length === 0 ? <div className="access-empty is-compact"><h3>Keine passenden Gäste</h3><p>Ändere die Suche oder den Tag-Filter.</p></div> : <div className="access-guest-list">{filteredGuests.map((guest) => { const selectedTagIds = guestTagDrafts[guest.id] ?? guest.tagIds; return <article className="access-guest-card" key={guest.id}><div className="access-guest-heading"><div><h3>{guest.name}</h3><p>{guest.groupLabel}</p></div>{guest.isChild && <span>Kind</span>}</div>{tags.length === 0 ? <p className="access-no-tags">Erstelle zuerst einen Tag, bevor du Zuordnungen vornimmst.</p> : <fieldset className="access-tag-checkboxes" disabled={pendingGuestId !== null}><legend>Tags für {guest.name}</legend>{tags.map((tag) => { const inputId = `guest-${guest.id}-tag-${tag.id}`; return <label htmlFor={inputId} key={tag.id}><input checked={selectedTagIds.includes(tag.id)} className="form-check-input" id={inputId} onChange={(e) => toggleGuestTag(guest, tag.id, e.target.checked)} type="checkbox" /><span className="access-color-dot" style={{ backgroundColor: HEX_COLOR.test(tag.color) ? tag.color : DEFAULT_COLOR }} /><span>{tag.name}</span></label>; })}</fieldset>}{guestErrorOwner === guest.id && guestTagErrors.length > 0 && <div className="access-field-error" role="alert">{guestTagErrors.map((message) => <p key={message}>{message}</p>)}</div>}<button className="access-primary-button" disabled={pendingGuestId !== null || tags.length === 0} onClick={() => saveGuestTags(guest)} type="button">{pendingGuestId === guest.id ? 'Wird gespeichert …' : 'Zuordnung speichern'}</button></article>; })}</div>}
                        </section>
                    </div>
                )}
            </main>
        </>
    );
}
