import { useCallback, useEffect, useRef, useState } from 'react';
import type { MatrixClient, Room } from 'matrix-js-sdk';
import {
  connectLiveMatrixClient,
  listJoinedRooms,
  loadManualSession,
  peekPaarrotSession,
  pickDefaultRoom,
  saveManualSession,
  stopLiveMatrixClient,
  type LiveConnectMode,
  type ManualSessionInput,
} from './liveClient';

type LiveState = {
  mode: LiveConnectMode;
  status: 'idle' | 'connecting' | 'ready' | 'error';
  error: string | null;
  client: MatrixClient | null;
  room: Room | null;
  rooms: Room[];
  sessionLabel: string | null;
};

const initial: LiveState = {
  mode: 'mock',
  status: 'idle',
  error: null,
  client: null,
  room: null,
  rooms: [],
  sessionLabel: null,
};

export function usePlaygroundMatrix() {
  const [state, setState] = useState<LiveState>(initial);
  const clientRef = useRef<MatrixClient | null>(null);
  const roomIdRef = useRef<string | undefined>(undefined);
  const paarrotSession = peekPaarrotSession();
  const hasPaarrotSession = Boolean(paarrotSession);
  const hasManualSession = Boolean(loadManualSession());

  const teardown = useCallback(() => {
    stopLiveMatrixClient(clientRef.current);
    clientRef.current = null;
  }, []);

  useEffect(() => () => teardown(), [teardown]);

  const selectRoom = useCallback((roomId: string) => {
    roomIdRef.current = roomId;
    setState((prev) => {
      if (!prev.client) return prev;
      const room = pickDefaultRoom(prev.client, roomId) ?? null;
      return { ...prev, room };
    });
  }, []);

  const connectLive = useCallback(
    async (manual?: ManualSessionInput) => {
      teardown();
      setState((prev) => ({
        ...prev,
        mode: 'live',
        status: 'connecting',
        error: null,
        client: null,
        room: null,
        rooms: [],
        sessionLabel: null,
      }));

      try {
        if (manual) saveManualSession(manual);
        const mx = await connectLiveMatrixClient(manual);
        clientRef.current = mx;
        const rooms = listJoinedRooms(mx);
        const room = pickDefaultRoom(mx, roomIdRef.current) ?? null;
        if (room) roomIdRef.current = room.roomId;

        const hs =
          peekPaarrotSession()?.baseUrl ??
          loadManualSession()?.baseUrl ??
          '';
        setState({
          mode: 'live',
          status: 'ready',
          error: null,
          client: mx,
          room,
          rooms,
          sessionLabel: `${mx.getUserId() ?? '?'} · ${hs}`,
        });
      } catch (err) {
        clientRef.current = null;
        setState({
          ...initial,
          mode: 'live',
          status: 'error',
          error: err instanceof Error ? err.message : String(err),
        });
      }
    },
    [teardown]
  );

  const useMocks = useCallback(() => {
    teardown();
    roomIdRef.current = undefined;
    setState(initial);
  }, [teardown]);

  return {
    ...state,
    hasPaarrotSession,
    hasManualSession,
    paarrotUserId: paarrotSession?.userId ?? null,
    paarrotBaseUrl: paarrotSession?.baseUrl ?? null,
    connectLive,
    useMocks,
    selectRoom,
  };
}
