"use client";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useCallback, useState } from "react";
import { cn } from "@stigmer/theme";
import { getUserMessage } from "@stigmer/sdk";
import { IamRole } from "@stigmer/protos/ai/stigmer/iam/v1/enum_pb";
import { timestampDate } from "@bufbuild/protobuf/wkt";
import { useUpdateIdentityProvider } from "./useUpdateIdentityProvider";
/**
 * View and edit panel for an existing identity provider.
 *
 * In **view mode**, displays all OIDC configuration fields in a
 * structured label/value layout with an "Edit" button.
 *
 * In **edit mode**, fields become editable inputs. The SSO toggle and
 * OIDC client ID are editable. "Save" submits the update via
 * {@link useUpdateIdentityProvider}; "Cancel" discards changes and
 * returns to view mode.
 *
 * All visual properties flow through `--stgm-*` design tokens.
 *
 * @example
 * ```tsx
 * <IdentityProviderDetailPanel
 *   identityProvider={idp}
 *   onUpdated={(updated) => refetch()}
 *   onBack={() => setFlow({ phase: "idle" })}
 * />
 * ```
 */
export function IdentityProviderDetailPanel({ identityProvider, onUpdated, onBack, ssoLoginUrl, className, }) {
    const spec = identityProvider.spec;
    const meta = identityProvider.metadata;
    const { update, isUpdating, error, clearError } = useUpdateIdentityProvider();
    const [mode, setMode] = useState("view");
    // Edit form state — initialized from current resource
    const [displayName, setDisplayName] = useState(spec?.displayName ?? "");
    const [jwksUri, setJwksUri] = useState(spec?.jwksUri ?? "");
    const [issuers, setIssuers] = useState(spec?.allowedIssuers.join(", ") ?? "");
    const [audience, setAudience] = useState(spec?.expectedAudience ?? "");
    const [userinfoEndpoint, setUserinfoEndpoint] = useState(spec?.userinfoEndpoint ?? "");
    const [isSso, setIsSso] = useState(spec?.isSsoProvider ?? false);
    const [oidcClientId, setOidcClientId] = useState(spec?.oidcClientId ?? "");
    // JIT provisioning
    const [autoProvision, setAutoProvision] = useState(spec?.autoProvisionAccounts ?? false);
    const [autoGrant, setAutoGrant] = useState(spec?.autoGrantOnOrg ?? false);
    const [autoGrantRole, setAutoGrantRole] = useState(spec?.autoGrantRole ?? IamRole.iam_role_unspecified);
    const [tenantOrgClaim, setTenantOrgClaim] = useState(spec?.tenantOrgClaim ?? "");
    const handleAutoProvisionChange = useCallback((v) => {
        setAutoProvision(v);
        if (!v) {
            setAutoGrant(false);
            setAutoGrantRole(IamRole.iam_role_unspecified);
            setTenantOrgClaim("");
        }
    }, []);
    const handleAutoGrantChange = useCallback((v) => {
        setAutoGrant(v);
        if (v)
            setAutoProvision(true);
        if (!v) {
            setAutoGrantRole(IamRole.iam_role_unspecified);
            setTenantOrgClaim("");
        }
    }, []);
    const enterEdit = useCallback(() => {
        setDisplayName(spec?.displayName ?? "");
        setJwksUri(spec?.jwksUri ?? "");
        setIssuers(spec?.allowedIssuers.join(", ") ?? "");
        setAudience(spec?.expectedAudience ?? "");
        setUserinfoEndpoint(spec?.userinfoEndpoint ?? "");
        setIsSso(spec?.isSsoProvider ?? false);
        setOidcClientId(spec?.oidcClientId ?? "");
        setAutoProvision(spec?.autoProvisionAccounts ?? false);
        setAutoGrant(spec?.autoGrantOnOrg ?? false);
        setAutoGrantRole(spec?.autoGrantRole ?? IamRole.iam_role_unspecified);
        setTenantOrgClaim(spec?.tenantOrgClaim ?? "");
        clearError();
        setMode("edit");
    }, [spec, clearError]);
    const cancelEdit = useCallback(() => {
        clearError();
        setMode("view");
    }, [clearError]);
    const handleSave = useCallback(async (e) => {
        e.preventDefault();
        clearError();
        try {
            const updated = await update({
                name: meta?.name ?? "",
                slug: meta?.slug,
                org: meta?.org ?? "",
                displayName: displayName.trim(),
                jwksUri: jwksUri.trim(),
                allowedIssuers: issuers
                    .split(",")
                    .map((s) => s.trim())
                    .filter(Boolean),
                expectedAudience: audience.trim(),
                userinfoEndpoint: userinfoEndpoint.trim() || undefined,
                isSsoProvider: isSso,
                oidcClientId: isSso ? oidcClientId.trim() : undefined,
                ...(!isSso && {
                    autoProvisionAccounts: autoProvision,
                    autoGrantOnOrg: autoGrant,
                    ...(autoGrant && autoGrantRole !== IamRole.iam_role_unspecified && {
                        autoGrantRole,
                    }),
                    ...(autoGrant && tenantOrgClaim.trim() && {
                        tenantOrgClaim: tenantOrgClaim.trim(),
                    }),
                }),
            });
            setMode("view");
            onUpdated?.(updated);
        }
        catch {
            // error state is managed by useUpdateIdentityProvider
        }
    }, [
        meta, displayName, jwksUri, issuers, audience,
        userinfoEndpoint, isSso, oidcClientId, autoProvision, autoGrant,
        autoGrantRole, tenantOrgClaim, update, clearError, onUpdated,
    ]);
    const canSave = displayName.trim() !== "" &&
        jwksUri.trim() !== "" &&
        issuers.trim() !== "" &&
        audience.trim() !== "" &&
        (!isSso || oidcClientId.trim() !== "") &&
        !isUpdating;
    const createdAt = identityProvider.status?.audit?.specAudit?.createdAt;
    const updatedAt = identityProvider.status?.audit?.specAudit?.updatedAt;
    return (_jsxs("div", { className: cn("space-y-4", className), children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [onBack && (_jsxs("button", { type: "button", onClick: onBack, className: "text-muted-foreground hover:text-foreground mb-1 flex items-center gap-1 text-xs transition-colors", children: [_jsx(ArrowLeftIcon, {}), "Back to list"] })), _jsx("h3", { className: "text-foreground truncate text-sm font-semibold", children: spec?.displayName || meta?.name || "Identity Provider" }), _jsxs("div", { className: "flex items-center gap-2", children: [meta?.slug && (_jsx("span", { className: "text-muted-foreground font-mono text-xs", children: meta.slug })), _jsx(ProvisioningModeBadge, { spec: spec })] })] }), mode === "view" && (_jsx("button", { type: "button", onClick: enterEdit, className: cn("shrink-0 rounded-md px-2.5 py-1.5 text-xs font-medium", "text-muted-foreground hover:text-foreground hover:bg-accent-hover", "transition-colors"), children: "Edit" }))] }), mode === "view" ? (_jsx(ViewMode, { spec: spec, ssoLoginUrl: ssoLoginUrl, createdAt: createdAt, updatedAt: updatedAt })) : (_jsxs("form", { onSubmit: handleSave, className: "space-y-3", children: [_jsx(FieldInput, { id: "stgm-idp-edit-name", label: "Display name", value: displayName, onChange: setDisplayName, placeholder: "e.g., Acme Corp SSO", disabled: isUpdating, required: true }), _jsx(FieldInput, { id: "stgm-idp-edit-jwks", label: "JWKS URI", value: jwksUri, onChange: setJwksUri, placeholder: "https://example.com/.well-known/jwks.json", disabled: isUpdating, required: true }), _jsx(FieldInput, { id: "stgm-idp-edit-issuers", label: "Allowed issuers", value: issuers, onChange: setIssuers, placeholder: "https://issuer.example.com/", hint: "Comma-separated list of trusted JWT issuer values", disabled: isUpdating, required: true }), _jsx(FieldInput, { id: "stgm-idp-edit-audience", label: "Expected audience", value: audience, onChange: setAudience, placeholder: "stigmer-api", disabled: isUpdating, required: true }), _jsx(FieldInput, { id: "stgm-idp-edit-userinfo", label: "Userinfo endpoint", value: userinfoEndpoint, onChange: setUserinfoEndpoint, placeholder: "https://example.com/userinfo", hint: "Optional \u2014 used to fetch user profile data", disabled: isUpdating }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", role: "switch", "aria-checked": isSso, onClick: () => setIsSso((v) => !v), disabled: isUpdating, className: cn("relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors", isSso ? "bg-primary" : "bg-muted", "disabled:pointer-events-none disabled:opacity-50"), children: _jsx("span", { className: cn("pointer-events-none inline-block h-4 w-4 rounded-full bg-background shadow-sm ring-0 transition-transform", isSso ? "translate-x-4" : "translate-x-0") }) }), _jsx("span", { className: "text-xs font-medium text-foreground", children: "SSO provider" })] }), isSso && (_jsx(FieldInput, { id: "stgm-idp-edit-client-id", label: "OIDC client ID", value: oidcClientId, onChange: setOidcClientId, placeholder: "public-client-id", hint: "Client ID for the PKCE-based Authorization Code flow", disabled: isUpdating, required: true })), _jsx(JitEditSection, { isSso: isSso, autoProvision: autoProvision, onAutoProvisionChange: handleAutoProvisionChange, autoGrant: autoGrant, onAutoGrantChange: handleAutoGrantChange, autoGrantRole: autoGrantRole, onAutoGrantRoleChange: setAutoGrantRole, tenantOrgClaim: tenantOrgClaim, onTenantOrgClaimChange: setTenantOrgClaim, disabled: isUpdating }), error && (_jsx("p", { className: "text-destructive text-[0.65rem]", role: "alert", children: getUserMessage(error) })), _jsxs("div", { className: "flex items-center gap-2 pt-1", children: [_jsxs("button", { type: "submit", disabled: !canSave, className: cn("inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium", "bg-primary text-primary-foreground hover:bg-primary-hover", "disabled:pointer-events-none disabled:opacity-40"), children: [isUpdating && _jsx(SpinnerIcon, {}), "Save changes"] }), _jsx("button", { type: "button", onClick: cancelEdit, disabled: isUpdating, className: cn("rounded-md px-2.5 py-1.5 text-xs", "text-muted-foreground hover:text-foreground hover:bg-accent-hover", "disabled:pointer-events-none disabled:opacity-50"), children: "Cancel" })] })] }))] }));
}
// ---------------------------------------------------------------------------
// View mode
// ---------------------------------------------------------------------------
function ViewMode({ spec, ssoLoginUrl, createdAt, updatedAt, }) {
    return (_jsxs("dl", { className: "space-y-2.5", children: [_jsx(Field, { label: "JWKS URI", value: spec?.jwksUri, mono: true }), _jsx(Field, { label: "Allowed issuers", value: spec?.allowedIssuers.join(", "), mono: true }), _jsx(Field, { label: "Expected audience", value: spec?.expectedAudience, mono: true }), spec?.userinfoEndpoint && (_jsx(Field, { label: "Userinfo endpoint", value: spec.userinfoEndpoint, mono: true })), spec?.isSsoProvider && (_jsx(Field, { label: "OIDC client ID", value: spec.oidcClientId, mono: true })), spec?.isSsoProvider && ssoLoginUrl && (_jsx(CopyableField, { label: "SSO login URL", value: ssoLoginUrl, hint: "Share this URL with your team members to sign in via SSO" })), (spec?.rateLimitBudget ?? 0) > 0 && (_jsx(Field, { label: "Rate limit", value: `${spec.rateLimitBudget} req/min` })), !spec?.isSsoProvider && spec?.autoProvisionAccounts && (_jsxs(_Fragment, { children: [_jsx("hr", { className: "border-border-muted" }), _jsx(Field, { label: "Auto-provision accounts", value: spec.autoProvisionAccounts ? "Enabled" : "Disabled" }), _jsx(Field, { label: "Auto-grant on organization", value: spec.autoGrantOnOrg ? "Enabled" : "Disabled" }), spec.autoGrantOnOrg && (_jsx(Field, { label: "Auto-grant role", value: formatIamRole(spec.autoGrantRole) })), spec.autoGrantOnOrg && spec.tenantOrgClaim && (_jsx(Field, { label: "Tenant org claim", value: spec.tenantOrgClaim, mono: true }))] })), _jsxs("div", { className: "flex gap-6", children: [createdAt && (_jsx(Field, { label: "Created", value: formatDate(timestampDate(createdAt)) })), updatedAt && (_jsx(Field, { label: "Updated", value: formatDate(timestampDate(updatedAt)) }))] })] }));
}
function Field({ label, value, mono, }) {
    if (!value)
        return null;
    return (_jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground text-[0.65rem] font-medium", children: label }), _jsx("dd", { className: cn("text-foreground mt-0.5 break-all text-xs", mono && "font-mono"), children: value })] }));
}
// ---------------------------------------------------------------------------
// View mode — copyable field
// ---------------------------------------------------------------------------
const COPIED_FEEDBACK_MS = 2000;
function CopyableField({ label, value, hint, }) {
    const [copied, setCopied] = useState(false);
    const valueId = "stgm-idp-sso-login-url";
    const handleCopy = useCallback(async () => {
        try {
            await navigator.clipboard.writeText(value);
            setCopied(true);
            setTimeout(() => setCopied(false), COPIED_FEEDBACK_MS);
        }
        catch {
            const el = document.getElementById(valueId);
            if (el) {
                const selection = window.getSelection();
                const range = document.createRange();
                range.selectNodeContents(el);
                selection?.removeAllRanges();
                selection?.addRange(range);
            }
        }
    }, [value]);
    return (_jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground text-[0.65rem] font-medium", children: label }), _jsxs("dd", { className: "mt-0.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { id: valueId, className: "text-foreground break-all font-mono text-xs select-all", children: value }), _jsx("button", { type: "button", onClick: handleCopy, className: cn("shrink-0 rounded px-1.5 py-0.5 text-[0.6rem]", "text-muted-foreground hover:text-foreground hover:bg-accent-hover", "transition-colors"), "aria-label": `Copy ${label}`, children: copied ? "Copied" : "Copy" })] }), hint && (_jsx("p", { className: "text-muted-foreground mt-0.5 text-[0.65rem]", children: hint })), _jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: copied && "SSO login URL copied to clipboard" })] })] }));
}
// ---------------------------------------------------------------------------
// Shared primitives
// ---------------------------------------------------------------------------
function FieldInput({ id, label, value, onChange, placeholder, hint, disabled, required, }) {
    return (_jsxs("div", { className: "space-y-1", children: [_jsx("label", { htmlFor: id, className: "text-xs font-medium text-foreground", children: label }), _jsx("input", { id: id, type: "text", value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, disabled: disabled, required: required, className: cn("w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground", "placeholder:text-muted-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50") }), hint && (_jsx("p", { className: "text-[0.65rem] text-muted-foreground", children: hint }))] }));
}
// ---------------------------------------------------------------------------
// Provisioning mode badge
// ---------------------------------------------------------------------------
function ProvisioningModeBadge({ spec }) {
    if (spec?.isSsoProvider) {
        return (_jsx("span", { className: "inline-flex items-center rounded-full border border-primary/30 bg-primary-subtle px-2 py-0.5 text-[0.65rem] font-medium text-primary", children: "SSO" }));
    }
    if (spec?.autoProvisionAccounts) {
        return (_jsx("span", { className: "inline-flex items-center rounded-full border border-primary/30 bg-primary-subtle px-2 py-0.5 text-[0.65rem] font-medium text-primary", children: "JIT" }));
    }
    return null;
}
// ---------------------------------------------------------------------------
// JIT edit section
// ---------------------------------------------------------------------------
const JIT_ROLE_OPTIONS = [
    { value: String(IamRole.iam_role_unspecified), label: "Default (viewer)" },
    { value: String(IamRole.viewer), label: "Viewer" },
    { value: String(IamRole.member), label: "Member" },
    { value: String(IamRole.admin), label: "Admin" },
];
function JitEditSection({ isSso, autoProvision, onAutoProvisionChange, autoGrant, onAutoGrantChange, autoGrantRole, onAutoGrantRoleChange, tenantOrgClaim, onTenantOrgClaimChange, disabled, }) {
    if (isSso) {
        return (_jsx("div", { className: "rounded-md border border-border-muted bg-muted-faint px-3 py-2", children: _jsxs("p", { className: "text-[0.65rem] text-muted-foreground", children: ["SSO providers automatically provision accounts and grant the", " ", _jsx("span", { className: "font-medium text-foreground", children: "viewer" }), " role on the owning organization. JIT provisioning settings are not applicable."] }) }));
    }
    return (_jsxs("fieldset", { className: "space-y-2.5", disabled: disabled, children: [_jsx("hr", { className: "border-border-muted" }), _jsx("legend", { className: "text-xs font-medium text-foreground", children: "JIT provisioning" }), _jsx("p", { className: "text-[0.65rem] text-muted-foreground", children: "Configure automatic account creation and role assignment for users authenticating with this provider." }), _jsx(ToggleSwitch, { checked: autoProvision, onChange: onAutoProvisionChange, label: "Auto-provision accounts", hint: "Create a federated account automatically on first authentication", disabled: disabled }), _jsx(ToggleSwitch, { checked: autoGrant, onChange: onAutoGrantChange, label: "Auto-grant on organization", hint: "Grant a role on the owning organization when an account is provisioned", disabled: disabled || !autoProvision }), autoGrant && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-1", children: [_jsx("label", { htmlFor: "stgm-idp-edit-grant-role", className: "text-xs font-medium text-foreground", children: "Auto-grant role" }), _jsx("select", { id: "stgm-idp-edit-grant-role", value: String(autoGrantRole), onChange: (e) => onAutoGrantRoleChange(Number(e.target.value)), disabled: disabled, className: cn("w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50"), children: JIT_ROLE_OPTIONS.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) }), _jsx("p", { className: "text-[0.65rem] text-muted-foreground", children: "Role granted automatically \u2014 org admins can upgrade later" })] }), _jsx(FieldInput, { id: "stgm-idp-edit-tenant-claim", label: "Tenant org claim", value: tenantOrgClaim, onChange: onTenantOrgClaimChange, placeholder: "e.g., org_id", hint: "JWT claim name that maps to a platform-managed organization (max 256 chars)", disabled: disabled })] }))] }));
}
// ---------------------------------------------------------------------------
// Toggle switch
// ---------------------------------------------------------------------------
function ToggleSwitch({ checked, onChange, label, hint, disabled, }) {
    return (_jsxs("div", { className: "space-y-0.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", role: "switch", "aria-checked": checked, onClick: () => onChange(!checked), disabled: disabled, className: cn("relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors", checked ? "bg-primary" : "bg-muted", "disabled:pointer-events-none disabled:opacity-50"), children: _jsx("span", { className: cn("pointer-events-none inline-block h-4 w-4 rounded-full bg-background shadow-sm ring-0 transition-transform", checked ? "translate-x-4" : "translate-x-0") }) }), _jsx("span", { className: "text-xs font-medium text-foreground", children: label })] }), hint && (_jsx("p", { className: "pl-11 text-[0.65rem] text-muted-foreground", children: hint }))] }));
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function formatIamRole(role) {
    switch (role) {
        case IamRole.viewer: return "Viewer";
        case IamRole.member: return "Member";
        case IamRole.admin: return "Admin";
        case IamRole.owner: return "Owner";
        default: return "Viewer (default)";
    }
}
function formatDate(date) {
    return date.toLocaleDateString(undefined, {
        month: "short",
        day: "numeric",
        year: "numeric",
    });
}
// ---------------------------------------------------------------------------
// Icons
// ---------------------------------------------------------------------------
function ArrowLeftIcon() {
    return (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M10 3L5 8l5 5" }) }));
}
function SpinnerIcon() {
    return (_jsx("svg", { width: "12", height: "12", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", className: "animate-spin", "aria-hidden": "true", children: _jsx("path", { d: "M8 2a6 6 0 1 0 6 6" }) }));
}
//# sourceMappingURL=IdentityProviderDetailPanel.js.map