'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useCallback, useEffect, useMemo, useState } from 'react';
import { ArrowLeft, GitMerge, Loader2, Pencil, Plus, Trash2, X } from 'lucide-react';
import { toast } from 'sonner';
import { createPageTag, deletePageTagWithDetach, fetchPages, mergePageTags, updatePageTag, } from '../../lib/pages-service.js';
import { PageTagPill, tagDotColor } from '../../components/pages/tag-badges.js';
import { ConfirmDialog } from '../../components/ui/ConfirmDialog.js';
const TAG_COLORS = ['purple', 'green', 'orange', 'red', 'blue', 'pink', 'gray'];
/**
 * /pages/tags — create, rename, recolor, merge, and delete page tags.
 *
 * Tags are documents in the hidden `page-tags` collection; pages
 * reference them by slug in `data.tags`. Deleting a tag detaches it
 * from every page first so no dangling slugs remain.
 */
export function PageTagManager({ onNavigate, startCreating = false }) {
    const [tags, setTags] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [refreshToken, setRefreshToken] = useState(0);
    const [creating, setCreating] = useState(startCreating);
    const [pendingDelete, setPendingDelete] = useState(null);
    const existingSlugs = useMemo(() => new Set(tags.map((t) => t.slug)), [tags]);
    const load = useCallback(async () => {
        setLoading(true);
        setError(null);
        try {
            // fetchPages returns tags with accurate page counts.
            const res = await fetchPages({ pageSize: 1 });
            setTags(res.tags);
        }
        catch (err) {
            setError(err instanceof Error ? err.message : 'Failed to load tags');
        }
        finally {
            setLoading(false);
        }
    }, []);
    useEffect(() => {
        void load();
    }, [load, refreshToken]);
    const refresh = () => setRefreshToken((t) => t + 1);
    const handleDelete = async (tag) => {
        const promise = deletePageTagWithDetach(tag);
        toast.promise(promise, {
            loading: `Deleting "${tag.name}"…`,
            success: () => `Deleted "${tag.name}"`,
            error: 'Failed to delete tag',
        });
        await promise;
        setPendingDelete(null);
        refresh();
    };
    return (_jsxs("div", { className: "p-4 pr-8 sm:p-6", children: [_jsxs("button", { type: "button", onClick: () => onNavigate('/pages'), className: "text-muted-foreground hover:text-foreground mb-4 inline-flex items-center gap-1.5 text-sm", children: [_jsx(ArrowLeft, { className: "h-4 w-4", "aria-hidden": true }), "Back to Pages"] }), _jsxs("div", { className: "mb-5 flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-foreground mb-1 text-xl font-medium tracking-tight sm:text-2xl", children: "Page Tags" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Organize pages with reusable, color-coded labels." })] }), !creating && (_jsxs("button", { type: "button", onClick: () => setCreating(true), className: "bg-primary text-primary-foreground hover:bg-primary/90 inline-flex items-center gap-1.5 rounded-lg px-3.5 py-1.5 text-sm font-medium shadow-sm transition-colors", children: [_jsx(Plus, { className: "h-3.5 w-3.5", "aria-hidden": true }), "New tag"] }))] }), creating && (_jsx(CreateTagForm, { existingSlugs: existingSlugs, onCancel: () => setCreating(false), onCreated: () => {
                    setCreating(false);
                    refresh();
                } })), loading ? (_jsxs("div", { className: "flex h-48 items-center justify-center", role: "status", "aria-live": "polite", children: [_jsx(Loader2, { className: "text-primary h-6 w-6 animate-spin", "aria-hidden": true }), _jsx("span", { className: "sr-only", children: "Loading tags" })] })) : error ? (_jsxs("div", { className: "border-border bg-card flex items-center gap-3 rounded-lg border p-3", children: [_jsx("span", { className: "text-foreground flex-1 text-sm", children: error }), _jsx("button", { type: "button", onClick: refresh, className: "border-border text-foreground hover:bg-accent rounded-md border px-3 py-1 text-sm", children: "Retry" })] })) : tags.length === 0 ? (_jsxs("div", { className: "border-border bg-card rounded-lg border p-8 text-center", children: [_jsx("h2", { className: "text-foreground mb-1 text-lg font-medium", children: "No tags yet" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Create a tag to start organizing pages." })] })) : (_jsx("div", { className: "bg-card border-border divide-border divide-y overflow-hidden rounded-xl border shadow-sm", children: tags.map((tag) => (_jsx(TagRow, { tag: tag, allTags: tags, onChanged: refresh, onRequestDelete: () => setPendingDelete(tag) }, tag.docId))) })), _jsx(ConfirmDialog, { open: pendingDelete !== null, title: `Delete "${pendingDelete?.name ?? ''}"?`, description: pendingDelete && pendingDelete.pageCount > 0
                    ? `This tag is used on ${pendingDelete.pageCount} page${pendingDelete.pageCount === 1 ? '' : 's'}. It will be removed from those pages. This cannot be undone.`
                    : 'This tag has no pages. Deleting it cannot be undone.', confirmLabel: "Delete tag", destructive: true, onClose: () => setPendingDelete(null), onConfirm: () => {
                    if (pendingDelete)
                        void handleDelete(pendingDelete);
                } })] }));
}
// ─── Create form ─────────────────────────────────────────────────────
function CreateTagForm({ existingSlugs, onCancel, onCreated, }) {
    const [name, setName] = useState('');
    const [color, setColor] = useState('purple');
    const [submitting, setSubmitting] = useState(false);
    const slug = name
        .toLowerCase()
        .trim()
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '');
    const duplicate = slug.length > 0 && existingSlugs.has(slug);
    const canSubmit = slug.length > 0 && !duplicate && !submitting;
    const submit = async () => {
        if (!canSubmit)
            return;
        setSubmitting(true);
        const res = await createPageTag({ name: name.trim(), color });
        setSubmitting(false);
        if (res.error) {
            toast.error(res.error);
            return;
        }
        toast.success(`Created "${name.trim()}"`);
        onCreated();
    };
    return (_jsxs("div", { className: "border-border bg-card mb-5 rounded-xl border p-4 shadow-sm", children: [_jsxs("div", { className: "flex flex-wrap items-end gap-3", children: [_jsxs("label", { className: "flex-1", children: [_jsx("span", { className: "text-foreground mb-1 block text-sm font-medium", children: "Tag name" }), _jsx("input", { type: "text", value: name, autoFocus: true, onChange: (e) => setName(e.target.value), onKeyDown: (e) => {
                                    if (e.key === 'Enter')
                                        void submit();
                                }, placeholder: "e.g. Marketing", className: "border-border bg-input-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none" })] }), _jsx(ColorPicker, { value: color, onChange: setColor }), _jsxs("button", { type: "button", onClick: () => void submit(), disabled: !canSubmit, className: "bg-primary text-primary-foreground hover:bg-primary/90 inline-flex items-center gap-1.5 rounded-lg px-3.5 py-2 text-sm font-medium shadow-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: [submitting ? _jsx(Loader2, { className: "h-4 w-4 animate-spin", "aria-hidden": true }) : null, "Create"] }), _jsxs("button", { type: "button", onClick: onCancel, className: "text-muted-foreground hover:text-foreground inline-flex items-center gap-1 px-2 py-2 text-sm", children: [_jsx(X, { className: "h-4 w-4", "aria-hidden": true }), "Cancel"] })] }), duplicate && (_jsx("p", { className: "text-destructive mt-2 text-xs", children: "A tag with that name already exists." }))] }));
}
function ColorPicker({ value, onChange }) {
    return (_jsxs("div", { children: [_jsx("span", { className: "text-foreground mb-1 block text-sm font-medium", children: "Color" }), _jsx("div", { className: "flex items-center gap-1.5", role: "radiogroup", "aria-label": "Tag color", children: TAG_COLORS.map((c) => (_jsx("button", { type: "button", role: "radio", "aria-checked": value === c, "aria-label": c, onClick: () => onChange(c), className: `h-7 w-7 rounded-full ${tagDotColor(c)} ring-offset-background transition-shadow ${value === c ? 'ring-ring ring-2 ring-offset-2' : ''}` }, c))) })] }));
}
// ─── Tag row ─────────────────────────────────────────────────────────
function TagRow({ tag, allTags, onChanged, onRequestDelete, }) {
    const [editing, setEditing] = useState(false);
    const [name, setName] = useState(tag.name);
    const [color, setColor] = useState(tag.color ?? 'gray');
    const [merging, setMerging] = useState(false);
    const save = async () => {
        const res = await updatePageTag(tag.docId, { name: name.trim(), color });
        if (res.error) {
            toast.error(res.error);
            return;
        }
        toast.success('Tag updated');
        setEditing(false);
        onChanged();
    };
    const merge = async (targetSlug) => {
        const target = allTags.find((t) => t.slug === targetSlug);
        if (!target)
            return;
        const promise = mergePageTags(tag, target);
        toast.promise(promise, {
            loading: `Merging "${tag.name}" into "${target.name}"…`,
            success: () => `Merged into "${target.name}"`,
            error: 'Merge failed',
        });
        await promise;
        setMerging(false);
        onChanged();
    };
    if (editing) {
        return (_jsxs("div", { className: "flex flex-wrap items-end gap-3 p-4", children: [_jsxs("label", { className: "flex-1", children: [_jsx("span", { className: "sr-only", children: "Tag name" }), _jsx("input", { type: "text", value: name, onChange: (e) => setName(e.target.value), className: "border-border bg-input-background text-foreground focus:border-primary focus:ring-primary/30 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none" })] }), _jsx(ColorPicker, { value: color, onChange: setColor }), _jsx("button", { type: "button", onClick: () => void save(), className: "bg-primary text-primary-foreground hover:bg-primary/90 rounded-lg px-3.5 py-2 text-sm font-medium", children: "Save" }), _jsx("button", { type: "button", onClick: () => {
                        setEditing(false);
                        setName(tag.name);
                        setColor(tag.color ?? 'gray');
                    }, className: "text-muted-foreground hover:text-foreground px-2 py-2 text-sm", children: "Cancel" })] }));
    }
    return (_jsxs("div", { className: "flex items-center gap-3 p-4", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [_jsx(PageTagPill, { name: tag.name, color: tag.color }), _jsxs("span", { className: "text-muted-foreground text-sm tabular-nums", children: [tag.pageCount, " page", tag.pageCount === 1 ? '' : 's'] })] }), merging ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("label", { className: "text-foreground inline-flex items-center gap-1.5 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Merge into:" }), _jsxs("select", { defaultValue: "", onChange: (e) => {
                                    if (e.target.value)
                                        void merge(e.target.value);
                                }, className: "border-border bg-card text-foreground rounded-lg border px-2.5 py-1.5 text-sm", children: [_jsx("option", { value: "", disabled: true, children: "Choose tag\u2026" }), allTags
                                        .filter((t) => t.slug !== tag.slug)
                                        .map((t) => (_jsx("option", { value: t.slug, children: t.name }, t.slug)))] })] }), _jsx("button", { type: "button", onClick: () => setMerging(false), className: "text-muted-foreground hover:text-foreground px-2 py-1 text-sm", children: "Cancel" })] })) : (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(IconAction, { label: `Edit ${tag.name}`, onClick: () => setEditing(true), children: _jsx(Pencil, { className: "h-4 w-4", "aria-hidden": true }) }), allTags.length > 1 && (_jsx(IconAction, { label: `Merge ${tag.name}`, onClick: () => setMerging(true), children: _jsx(GitMerge, { className: "h-4 w-4", "aria-hidden": true }) })), _jsx(IconAction, { label: `Delete ${tag.name}`, onClick: onRequestDelete, destructive: true, children: _jsx(Trash2, { className: "h-4 w-4", "aria-hidden": true }) })] }))] }));
}
function IconAction({ label, onClick, destructive, children, }) {
    return (_jsx("button", { type: "button", onClick: onClick, "aria-label": label, className: `hover:bg-accent inline-flex h-8 w-8 items-center justify-center rounded-md transition-colors ${destructive ? 'text-destructive hover:bg-destructive/10' : 'text-muted-foreground'}`, children: children }));
}
//# sourceMappingURL=PageTagManager.js.map