import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useState } from "react";
import { Check, ChevronDown, ChevronRight, Pencil, Plus, Trash2 } from "lucide-react";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import { Select } from "../../components/ui/select";
import { useEditContext } from "../../editor/client/editContext";
import { ItemCollectionPicker, isGuid } from "./ItemCollectionPicker";
import { deleteProjectProperty, getProjectProperties, upsertProjectProperties, } from "../services/taskService";
const HIDDEN_PROJECT_PROPERTY_KEYS = new Set(["taskboard.graphLayout.v1"]);
function toDrafts(properties) {
    return properties
        .filter((property) => !HIDDEN_PROJECT_PROPERTY_KEYS.has(property.propertyKey))
        .map((property) => ({
        localId: property.propertyId || `${property.projectId}-${property.propertyKey}`,
        persisted: true,
        propertyKey: property.propertyKey,
        valueType: property.valueType,
        stringValue: property.stringValue ?? "",
        itemCollectionId: property.itemCollectionId ?? "",
    }));
}
export function ProjectPropertiesPanel(props) {
    const { projectId, canEdit, className } = props;
    const editContext = useEditContext();
    const [drafts, setDrafts] = useState([]);
    const [loading, setLoading] = useState(false);
    const [savingLocalId, setSavingLocalId] = useState(null);
    const [editingLocalIds, setEditingLocalIds] = useState(new Set());
    const [error, setError] = useState(null);
    const [expanded, setExpanded] = useState(false);
    useEffect(() => {
        let disposed = false;
        async function load() {
            if (!projectId)
                return;
            setLoading(true);
            setError(null);
            try {
                const result = await getProjectProperties(projectId);
                if (disposed)
                    return;
                if (result.type === "success") {
                    setDrafts(toDrafts(result.data || []));
                    return;
                }
                setError(result.summary || "Failed to load project properties");
            }
            catch (requestError) {
                if (!disposed) {
                    setError(requestError instanceof Error
                        ? requestError.message
                        : "Failed to load project properties");
                }
            }
            finally {
                if (!disposed) {
                    setLoading(false);
                }
            }
        }
        void load();
        return () => {
            disposed = true;
        };
    }, [projectId]);
    useEffect(() => {
        const addListener = editContext?.addSocketMessageListener;
        if (!addListener || !projectId)
            return;
        const unsubscribe = addListener((message) => {
            if (message?.type !== "project:properties:updated")
                return;
            const payload = message?.payload ?? {};
            const msgProjectId = payload.projectId;
            if (msgProjectId !== projectId)
                return;
            void getProjectProperties(projectId).then((result) => {
                if (result.type === "success") {
                    setDrafts(toDrafts(result.data || []));
                    setEditingLocalIds(new Set());
                }
            });
        });
        return () => unsubscribe();
    }, [editContext, projectId]);
    function isRowValid(draft) {
        const key = draft.propertyKey.trim();
        if (!key)
            return false;
        if (draft.valueType === "itemCollectionRef")
            return isGuid(draft.itemCollectionId);
        return draft.stringValue != null;
    }
    function updateDraft(localId, patch) {
        setDrafts((current) => current.map((draft) => draft.localId === localId ? { ...draft, ...patch } : draft));
    }
    function addDraft() {
        const localId = `new-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
        setDrafts((current) => [
            ...current,
            {
                localId,
                persisted: false,
                propertyKey: "",
                valueType: "string",
                stringValue: "",
                itemCollectionId: "",
            },
        ]);
        setEditingLocalIds((prev) => new Set([...prev, localId]));
    }
    function startEditing(localId) {
        setEditingLocalIds((prev) => new Set([...prev, localId]));
    }
    async function removeRow(localId) {
        const draft = drafts.find((d) => d.localId === localId);
        if (!draft || !projectId)
            return;
        const remaining = drafts.filter((d) => d.localId !== localId);
        setError(null);
        if (draft.persisted) {
            setSavingLocalId(localId);
            try {
                const result = await deleteProjectProperty({
                    projectId,
                    propertyKey: draft.propertyKey.trim(),
                });
                if (result.type === "success") {
                    setDrafts(toDrafts(result.data || []));
                    setEditingLocalIds((prev) => {
                        const next = new Set(prev);
                        next.delete(localId);
                        return next;
                    });
                }
                else {
                    setError(result.summary || "Failed to delete property");
                }
            }
            catch (requestError) {
                setError(requestError instanceof Error
                    ? requestError.message
                    : "Failed to delete property");
            }
            finally {
                setSavingLocalId(null);
            }
        }
        else {
            setDrafts(remaining);
            setEditingLocalIds((prev) => {
                const next = new Set(prev);
                next.delete(localId);
                return next;
            });
        }
    }
    async function commitRow(localId) {
        if (!projectId)
            return;
        const draft = drafts.find((d) => d.localId === localId);
        if (!draft)
            return;
        if (!isRowValid(draft)) {
            setError("Key required; use valid GUID for Item Collection.");
            return;
        }
        setSavingLocalId(localId);
        setError(null);
        const properties = [];
        for (const d of drafts) {
            const propertyKey = d.propertyKey.trim();
            if (!propertyKey)
                continue;
            if (d.valueType === "itemCollectionRef") {
                properties.push({
                    propertyKey,
                    valueType: "itemCollectionRef",
                    itemCollectionId: d.itemCollectionId.trim(),
                });
            }
            else {
                properties.push({
                    propertyKey,
                    valueType: "string",
                    stringValue: d.stringValue ?? "",
                });
            }
        }
        const request = { projectId, properties };
        try {
            const result = await upsertProjectProperties(request);
            if (result.type === "success") {
                setDrafts(toDrafts(result.data || []));
                setEditingLocalIds((prev) => {
                    const next = new Set(prev);
                    next.delete(localId);
                    return next;
                });
            }
            else {
                setError(result.summary || "Failed to save project properties");
            }
        }
        catch (requestError) {
            setError(requestError instanceof Error
                ? requestError.message
                : "Failed to save project properties");
        }
        finally {
            setSavingLocalId(null);
        }
    }
    return (_jsxs("div", { className: `${className || ""}`, children: [_jsx("div", { className: "mb-2 flex cursor-pointer items-center justify-between gap-2 rounded-md transition-colors hover:bg-slate-50", onClick: () => setExpanded((e) => !e), onKeyDown: (e) => {
                    if (e.key === "Enter" || e.key === " ") {
                        e.preventDefault();
                        setExpanded((prev) => !prev);
                    }
                }, role: "button", tabIndex: 0, "aria-expanded": expanded, "aria-controls": "project-properties-content", id: "project-properties-header", "data-testid": "taskboard-project-properties-header", children: _jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1.5", children: [expanded ? (_jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-slate-500" })) : (_jsx(ChevronRight, { className: "h-4 w-4 shrink-0 text-slate-500" })), _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-[11px] font-semibold tracking-wider text-slate-500 uppercase", children: "Project Properties" }), expanded ? (_jsx("div", { className: "text-xs text-slate-600", children: "Shared key/value context for task agents. Keys: camelCase only (e.g. productScope)." })) : (_jsxs("div", { className: "text-xs text-slate-500", children: [drafts.length, " ", drafts.length === 1 ? "property" : "properties"] }))] })] }) }), expanded && (_jsxs("div", { id: "project-properties-content", "aria-labelledby": "project-properties-header", children: [loading ? (_jsx("div", { className: "text-xs text-slate-500", children: "Loading properties..." })) : null, error ? (_jsx("div", { className: "mb-2 text-xs text-red-600", children: error })) : null, _jsx("div", { className: "space-y-2", children: drafts.length === 0 ? (_jsx("div", { className: "rounded-md border border-dashed p-3 text-xs text-slate-500", children: "No properties yet." })) : (drafts.map((draft) => {
                            const isEditing = editingLocalIds.has(draft.localId);
                            const isSaving = savingLocalId === draft.localId;
                            const rowDisabled = !canEdit || isSaving;
                            const canCommit = isRowValid(draft);
                            return (_jsxs("div", { className: "grid grid-cols-[1fr_auto] gap-1.5 md:grid-cols-[minmax(0,1.1fr)_150px_minmax(0,1.2fr)_auto] rounded-xl border border-slate-200 bg-white p-4 shadow-sm", children: [_jsx(Input, { value: draft.propertyKey, disabled: rowDisabled || !isEditing, onChange: (event) => updateDraft(draft.localId, {
                                            propertyKey: event.target.value,
                                        }), placeholder: "e.g. productScope (camelCase)", className: "h-7 text-xs" }), _jsx(Select, { value: draft.valueType, disabled: rowDisabled || !isEditing, onValueChange: (value) => updateDraft(draft.localId, {
                                            valueType: value,
                                            stringValue: value === "itemCollectionRef"
                                                ? draft.stringValue
                                                : draft.stringValue,
                                            itemCollectionId: value === "itemCollectionRef"
                                                ? draft.itemCollectionId
                                                : "",
                                        }), options: [
                                            { value: "string", label: "String" },
                                            { value: "itemCollectionRef", label: "Item Collection" },
                                        ], className: "h-7 text-xs" }), draft.valueType === "itemCollectionRef" ? (_jsx("div", { className: "col-span-1", children: _jsx(ItemCollectionPicker, { value: draft.itemCollectionId, disabled: rowDisabled || !isEditing, onChange: (nextValue) => updateDraft(draft.localId, { itemCollectionId: nextValue }), compact: true, displayNameOnly: true }) })) : (_jsx(Input, { value: draft.stringValue, disabled: rowDisabled || !isEditing, onChange: (event) => updateDraft(draft.localId, {
                                            stringValue: event.target.value,
                                        }), placeholder: "String value", className: "h-7 text-xs col-span-1" })), _jsxs("div", { className: "flex shrink-0 items-center gap-0.5 col-span-1 justify-end", children: [isEditing ? (_jsx(Button, { size: "icon", variant: "ghost", className: "h-7 w-7", onClick: () => void commitRow(draft.localId), disabled: rowDisabled || !canCommit, title: "Commit", "data-testid": `taskboard-project-properties-commit-${draft.localId}`, children: isSaving ? (_jsx("span", { className: "h-3 w-3 animate-spin rounded-full border border-current border-t-transparent" })) : (_jsx(Check, { className: "h-3 w-3" })) })) : (_jsx(Button, { size: "icon", variant: "ghost", className: "h-7 w-7", onClick: () => startEditing(draft.localId), disabled: rowDisabled, title: "Edit", "data-testid": `taskboard-project-properties-edit-${draft.localId}`, children: _jsx(Pencil, { className: "h-3 w-3" }) })), _jsx(Button, { size: "icon", variant: "ghost", className: "h-7 w-7", onClick: () => void removeRow(draft.localId), disabled: rowDisabled || savingLocalId === draft.localId, title: "Delete", "data-testid": `taskboard-project-properties-delete-${draft.localId}`, children: savingLocalId === draft.localId && draft.persisted ? (_jsx("span", { className: "h-3 w-3 animate-spin rounded-full border border-current border-t-transparent" })) : (_jsx(Trash2, { className: "h-3 w-3" })) })] })] }, draft.localId));
                        })) }), _jsxs(Button, { size: "xs", variant: "secondary", onClick: addDraft, disabled: !canEdit || loading, className: "mt-3", "data-testid": "taskboard-project-properties-add", children: [_jsx(Plus, { className: "h-3 w-3" }), "Add"] })] }))] }));
}
//# sourceMappingURL=ProjectPropertiesPanel.js.map