import { useCallback, useEffect, useState } from 'react';
import { useAdapter } from '../provider';
import type { ChannelSummary, CreateChannelInput } from '../types';

export interface ChannelsState {
  /** Discoverable channels (public + private-I'm-in), each flagged `joined`. */
  browsable: ChannelSummary[];
  loading: boolean;
  error: string | null;
  /** Whether the adapter implements channels at all — drives showing/hiding the channels UI. */
  supported: boolean;
  refetch: () => void;
  create: (input: CreateChannelInput) => Promise<string>;
  join: (threadId: string) => Promise<void>;
  leave: (threadId: string) => Promise<void>;
}

export function useChannels(): ChannelsState {
  const adapter = useAdapter();
  const supported = typeof adapter.browseChannels === 'function';
  const [browsable, setBrowsable] = useState<ChannelSummary[]>([]);
  const [loading, setLoading] = useState(supported);
  const [error, setError] = useState<string | null>(null);
  const [nonce, setNonce] = useState(0);

  useEffect(() => {
    if (!adapter.browseChannels) {
      setLoading(false);
      return;
    }
    let alive = true;
    setLoading(true);
    adapter
      .browseChannels()
      .then((list) => {
        if (!alive) return;
        setBrowsable(list);
        setError(null);
      })
      .catch((e: unknown) => {
        if (!alive) return;
        setError(e instanceof Error ? e.message : String(e));
        setBrowsable([]);
      })
      .finally(() => {
        if (alive) setLoading(false);
      });
    return () => {
      alive = false;
    };
  }, [adapter, nonce]);

  const refetch = useCallback(() => setNonce((n) => n + 1), []);

  const create = useCallback(
    async (input: CreateChannelInput) => {
      if (!adapter.createChannel) throw new Error('channels not supported by this adapter');
      const { threadId } = await adapter.createChannel(input);
      setNonce((n) => n + 1);
      return threadId;
    },
    [adapter],
  );

  const join = useCallback(
    async (threadId: string) => {
      if (!adapter.joinChannel) throw new Error('channels not supported by this adapter');
      await adapter.joinChannel(threadId);
      setNonce((n) => n + 1);
    },
    [adapter],
  );

  const leave = useCallback(
    async (threadId: string) => {
      if (!adapter.leaveChannel) throw new Error('channels not supported by this adapter');
      await adapter.leaveChannel(threadId);
      setNonce((n) => n + 1);
    },
    [adapter],
  );

  return { browsable, loading, error, supported, refetch, create, join, leave };
}
