import { useCallback, useMemo, useState } from 'react';
import { where } from 'firebase/firestore';
import { useLiveParticleChildren } from '@/hooks/use-particle';
import { useAuthStore } from '@/stores/auth-store';
import { parseParticlePath, type ParticlePath } from '@/lib/particle-path';
import type { Particle } from '@/api/types';

const INITIAL_PAGE_SIZE = 9;
const PAGE_INCREMENT = 9;

// Stable references so the Firestore subscriptions don't re-attach per render.
const OPEN_STATUS_FILTER = where('status', '==', 'open');
const CLOSED_STATUS_FILTER = where('status', '==', 'closed');
const CONTAINER_TYPE_FILTER = where('type', 'in', ['stream', 'folder']);
const LEAF_TYPE_FILTER = where('type', 'in', [
  'media',
  'file',
  'text',
  'task',
  'paper',
]);

interface UseContainerChildrenOptions {
  /**
   * When set, list only streams with this status, filtered server-side like
   * the pre-folder query (reuses its composite indexes). Used by the network
   * root while folders are shelved; folders keep the full mixed-type behavior
   * so the container model can be picked back up later. Only streams carry
   * `status`, so the filter excludes other types by itself.
   */
  streamStatus?: 'open' | 'closed';
}

interface UseContainerChildrenResult {
  /** All visible children, sorted by latest activity (then creation). */
  items: Particle[];
  isLoading: boolean;
  canLoadMore: boolean;
  loadMore: () => void;
}

function activityTime(particle: Particle): number {
  if (
    (particle.type === 'stream' || particle.type === 'folder') &&
    particle.last_child_created_at
  ) {
    return particle.last_child_created_at.getTime();
  }
  return particle.created_at.getTime();
}

/**
 * Children of a container (network root or folder), all particle types.
 *
 * Two merged subscriptions because visibility scoping filters on `visible_to`
 * with array-contains-any, and leaf particles don't carry that field — a
 * single scoped query would silently exclude them. Containers (streams,
 * folders) are visibility-scoped; leaves inherit access from their container.
 */
export function useContainerChildren(
  path: ParticlePath,
  { streamStatus }: UseContainerChildrenOptions = {},
): UseContainerChildrenResult {
  const { networkId } = parseParticlePath(path);
  const userId = useAuthStore((s) => s.user?.id);

  const visibilityScopes = useMemo(() => {
    const scopes: string[] = [];
    if (userId) scopes.push(`human:${userId}`);
    scopes.push(`network:${networkId}`);
    return scopes;
  }, [userId, networkId]);

  const [limit, setLimit] = useState(INITIAL_PAGE_SIZE);

  const containerFilter = streamStatus
    ? streamStatus === 'open'
      ? OPEN_STATUS_FILTER
      : CLOSED_STATUS_FILTER
    : CONTAINER_TYPE_FILTER;

  const { children: containers, isLoading: containersLoading } =
    useLiveParticleChildren(path, {
      orderByField: 'last_child_created_at',
      orderDirection: 'desc',
      visibilityScopes,
      whereFilter: containerFilter,
      limit,
    });

  // Passing undefined disables the subscription entirely in streams-only mode.
  const { children: leaves, isLoading: leavesLoading } =
    useLiveParticleChildren(streamStatus ? undefined : path, {
      orderByField: 'created_at',
      orderDirection: 'desc',
      whereFilter: LEAF_TYPE_FILTER,
      limit,
    });

  const items = useMemo(
    () =>
      [...containers, ...leaves].sort(
        (a, b) => activityTime(b) - activityTime(a),
      ),
    [containers, leaves],
  );

  // Heuristic: a query returning a full page may have more behind it.
  const canLoadMore = containers.length >= limit || leaves.length >= limit;

  const loadMore = useCallback(() => {
    setLimit((prev) => prev + PAGE_INCREMENT);
  }, []);

  return {
    items,
    isLoading: containersLoading || leavesLoading,
    canLoadMore,
    loadMore,
  };
}
