// ---------------------------------------------------------------------------
// SP28: Inbox "Ack orphans" lane hook (D7).
//
// Fetches the three ack-kind orphan lists (999 / 277ca / ta1) and
// flattens them into a single lane of rows. The backend endpoint
// `/api/inbox/ack-orphans?kind=…` takes one kind at a time so the
// hook fires three parallel requests and merges by source_batch +
// ack_id (a single ack row never appears in two kinds' orphan lists,
// so the merge is just a concat).
//
// Refetch is wired through `useAckOrphans`'s `refetch` callback. The
// Inbox page calls it after a manual match lands (the orphan lane
// can drop a row that just got linked) — the same pattern the
// existing `useInboxLanes` uses for its tail-driven refetch.
// ---------------------------------------------------------------------------

import { useCallback, useEffect, useState } from "react";
import { api, type AckOrphanRow } from "@/lib/api";

export type AckOrphansState = {
  loading: boolean;
  error: Error | null;
  items: AckOrphanRow[];
  refetch: () => Promise<void>;
};

export function useAckOrphans(): AckOrphansState {
  const [items, setItems] = useState<AckOrphanRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  const refetch = useCallback(async () => {
    try {
      // Fire all three kind queries in parallel — the backend serves
      // each independently. Fail-soft per kind: if one of the three
      // returns a 5xx we surface the error and skip that kind so the
      // operator still sees the other two.
      const [a999, a277, aTa1] = await Promise.allSettled([
        api.listAckOrphans("999"),
        api.listAckOrphans("277ca"),
        api.listAckOrphans("ta1"),
      ]);
      const merged: AckOrphanRow[] = [];
      const errs: Error[] = [];
      for (const r of [a999, a277, aTa1] as const) {
        if (r.status === "fulfilled") {
          merged.push(...r.value);
        } else {
          errs.push(
            r.reason instanceof Error
              ? r.reason
              : new Error(String(r.reason)),
          );
        }
      }
      // Sort newest-first by parsedAt so the lane reads in the same
      // direction as the rest of the inbox.
      merged.sort((a, b) => {
        const at = Date.parse(a.parsedAt);
        const bt = Date.parse(b.parsedAt);
        return bt - at;
      });
      setItems(merged);
      // Only surface an error if EVERY kind failed; partial failures
      // show their rows and silently swallow the broken kind (the
      // operator can retry — a future improvement could surface a
      // per-kind "fetch failed" pill).
      setError(errs.length === 3 ? errs[0] : null);
    } catch (e) {
      setError(e as Error);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void refetch();
  }, [refetch]);

  return { items, loading, error, refetch };
}