'use client';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { validateSecuritySettings, } from '@actuate-media/cms-core/security-center';
import { cmsApi } from '../../lib/api.js';
const EMPTY_FORM = {
    mfaRequired: false,
    mfaGracePeriodDays: 7,
    maxConcurrentSessions: 5,
    timeoutHours: 168,
    idleLogoutEnabled: false,
    ipAllowlistText: '',
    auditLoggingEnabled: true,
};
/** Split the textarea into trimmed, de-duplicated entries (one per line). */
export function parseAllowlistText(text) {
    const out = [];
    for (const line of text.split('\n')) {
        const entry = line.trim();
        if (entry && !out.includes(entry))
            out.push(entry);
    }
    return out;
}
function formFromSettings(s) {
    return {
        mfaRequired: s.mfa.required,
        mfaGracePeriodDays: s.mfa.gracePeriodDays,
        maxConcurrentSessions: s.session.maxConcurrentSessions,
        timeoutHours: s.session.timeoutHours ?? 168,
        idleLogoutEnabled: s.session.idleLogoutEnabled ?? false,
        ipAllowlistText: (s.access?.ipAllowlist ?? []).join('\n'),
        auditLoggingEnabled: s.access?.auditLoggingEnabled ?? true,
    };
}
function formToSettings(f) {
    return {
        mfa: { required: f.mfaRequired, gracePeriodDays: f.mfaGracePeriodDays },
        session: {
            maxConcurrentSessions: f.maxConcurrentSessions,
            timeoutHours: f.timeoutHours,
            idleLogoutEnabled: f.idleLogoutEnabled,
        },
        access: {
            ipAllowlist: parseAllowlistText(f.ipAllowlistText),
            auditLoggingEnabled: f.auditLoggingEnabled,
        },
    };
}
/**
 * Loads the Security Center (`GET /security`) — computed posture, cross-module
 * summaries, secret/encryption verdicts — and tracks the small editable policy
 * (MFA requirement + grace, concurrent-session cap). Save is lockout-safe: the
 * client mirrors the server's MFA guard so the operator gets immediate feedback,
 * and the server re-checks authoritatively.
 */
export function useSecuritySettings(canEdit) {
    const [loading, setLoading] = useState(true);
    const [loadError, setLoadError] = useState(null);
    const [data, setData] = useState(null);
    const [baseline, setBaseline] = useState(EMPTY_FORM);
    const [form, setForm] = useState(EMPTY_FORM);
    const [saveState, setSaveState] = useState('idle');
    const [saveError, setSaveError] = useState(null);
    const [lockoutPrompt, setLockoutPrompt] = useState(null);
    const [revokeState, setRevokeState] = useState('idle');
    const [reloadKey, setReloadKey] = useState(0);
    useEffect(() => {
        let cancelled = false;
        setLoading(true);
        setLoadError(null);
        cmsApi('/security')
            .then((res) => {
            if (cancelled)
                return;
            if (res.error || !res.data) {
                setLoadError(res.error ?? 'Failed to load security settings.');
                return;
            }
            setData(res.data);
            const f = formFromSettings(res.data.settings);
            setBaseline(f);
            setForm(f);
        })
            .catch(() => {
            if (!cancelled)
                setLoadError('Failed to load security settings.');
        })
            .finally(() => {
            if (!cancelled)
                setLoading(false);
        });
        return () => {
            cancelled = true;
        };
    }, [reloadKey]);
    const setField = useCallback((key, value) => {
        setForm((prev) => ({ ...prev, [key]: value }));
        setSaveState('idle');
    }, []);
    const dirty = useMemo(() => Object.keys(form).some((k) => form[k] !== baseline[k]), [form, baseline]);
    const issues = useMemo(() => {
        const list = validateSecuritySettings(formToSettings(form));
        // Client mirror of the server's lockout-safe MFA guard: block enabling
        // org-wide MFA when the current admin has not set up MFA themselves.
        if (form.mfaRequired && !baseline.mfaRequired && data && !data.viewerHasMfa) {
            list.push({
                field: 'mfaRequired',
                message: 'Set up MFA for your own account before requiring it for everyone — otherwise you would lock yourself out.',
                severity: 'error',
            });
        }
        return list;
    }, [form, baseline.mfaRequired, data]);
    const hasErrors = issues.some((i) => i.severity === 'error');
    const save = useCallback(async (options) => {
        if (!canEdit || hasErrors || !dirty)
            return;
        setSaveState('saving');
        setSaveError(null);
        setLockoutPrompt(null);
        try {
            const res = await cmsApi('/security', {
                method: 'PUT',
                body: JSON.stringify({
                    ...formToSettings(form),
                    ...(options?.confirmLockout ? { confirmLockout: true } : {}),
                }),
            });
            // The server's lockout guard: surface a confirm dialog instead of a
            // generic failure so the operator can retry with confirmLockout.
            if (res.code === 'IP_LOCKOUT_RISK') {
                setSaveState('idle');
                setLockoutPrompt(res.error ?? 'This allowlist may lock you out. Save anyway?');
                return;
            }
            if (res.error || !res.data) {
                throw new Error(res.error ?? 'Failed to save security settings.');
            }
            setData(res.data);
            const f = formFromSettings(res.data.settings);
            setBaseline(f);
            setForm(f);
            setSaveState('success');
        }
        catch (err) {
            setSaveState('error');
            setSaveError(err instanceof Error ? err.message : 'Failed to save security settings.');
        }
    }, [canEdit, hasErrors, dirty, form]);
    const dismissLockoutPrompt = useCallback(() => setLockoutPrompt(null), []);
    const reset = useCallback(() => {
        setForm(baseline);
        setSaveState('idle');
        setSaveError(null);
        setLockoutPrompt(null);
    }, [baseline]);
    const refetch = useCallback(() => setReloadKey((k) => k + 1), []);
    const revokeAllOtherSessions = useCallback(async () => {
        setRevokeState('working');
        try {
            const res = await cmsApi('/security/sessions/revoke-all', {
                method: 'POST',
            });
            if (res.error)
                throw new Error(res.error);
            setRevokeState('done');
            // Refresh the active-session count.
            setReloadKey((k) => k + 1);
            return res.data?.revoked ?? 0;
        }
        catch {
            setRevokeState('error');
            return null;
        }
    }, []);
    return {
        loading,
        loadError,
        data,
        form,
        setField,
        dirty,
        issues,
        hasErrors,
        canEdit,
        saveState,
        saveError,
        save,
        reset,
        refetch,
        lockoutPrompt,
        dismissLockoutPrompt,
        revokeState,
        revokeAllOtherSessions,
    };
}
//# sourceMappingURL=useSecuritySettings.js.map