"use client" import { useCallback, useEffect, useRef, useState } from "react" import { serverListSchema, type ServerRead } from "@mmapp/contracts/servers" import { readCertificatesState } from "@/shared/api/certificates" import { requestJson } from "@/shared/api/http-client" import { mergeCertificateSnapshots, type CertificateSnapshots } from "@/lib/certificate-snapshots" export function useCertificateCatalog(backendUrl: string, live: boolean, canRead: boolean, canReadServers: boolean) { const [snapshots, setSnapshots] = useState({}) const [servers, setServers] = useState([]) const [hasState, setHasState] = useState(false) const [hasServers, setHasServers] = useState(false) const [loading, setLoading] = useState(live) const [error, setError] = useState(null) const [serverError, setServerError] = useState(null) const [collectedAt, setCollectedAt] = useState(null) const controller = useRef(null) const revision = useRef(0) const alive = useRef(true) const reload = useCallback(async () => { if (!live || !alive.current) return controller.current?.abort() const current = ++revision.current const abort = new AbortController() controller.current = abort const signal = AbortSignal.any([abort.signal, AbortSignal.timeout(30_000)]) const active = () => alive.current && !abort.signal.aborted && revision.current === current setLoading(true) await Promise.allSettled([ canRead ? readCertificatesState(backendUrl, { signal }).then(result => { if (!active()) return setSnapshots(previous => mergeCertificateSnapshots(previous, result)) setHasState(true) setCollectedAt(result.collectedAt) setError(null) }).catch(reason => { if (active()) setError(reason instanceof Error ? reason.message : "Ошибка каталога сертификатов") }) : Promise.resolve(), canReadServers ? requestJson(backendUrl, "/api/servers", { signal }).then(payload => { const result = serverListSchema.parse(payload) if (!active()) return setServers(result) setHasServers(true) setServerError(null) }).catch(reason => { if (active()) setServerError(reason instanceof Error ? reason.message : "Ошибка каталога серверов") }) : Promise.resolve(), ]) if (active()) setLoading(false) }, [backendUrl, live, canRead, canReadServers]) useEffect(() => { alive.current = true queueMicrotask(() => { if (alive.current) void reload() }) return () => { alive.current = false; controller.current?.abort() } }, [reload]) return { snapshots, servers, hasState, hasServers, loading, error, serverError, collectedAt, reload } }