import { startTransition, useEffect, useEffectEvent, useMemo, useState } from 'react';
import { useResearchEventSubscriptions } from '../lib/researchEvents';
import { researchBridge } from '../lib/researchBridge';
import type {
  CreateResearchWorkspaceRequest,
  ResearchNavigationIntent,
  ResearchWorkspace,
} from '../types/research';

interface UseResearchWorkspacesArgs {
  initialWorkspaceId?: string | null;
}

export interface EnsureResearchWorkspaceRequest {
  ticker?: string;
  workspaceId?: string | null;
}

export const upsertWorkspaceRecord = (
  current: ResearchWorkspace[],
  nextWorkspace: ResearchWorkspace,
): ResearchWorkspace[] => {
  const existingIndex = current.findIndex((workspace) => workspace.id === nextWorkspace.id);
  if (existingIndex === -1) {
    return [nextWorkspace, ...current];
  }

  return current.map((workspace) =>
    workspace.id === nextWorkspace.id ? nextWorkspace : workspace,
  );
};

export const useResearchWorkspaces = ({
  initialWorkspaceId,
}: UseResearchWorkspacesArgs = {}) => {
  const [workspaces, setWorkspaces] = useState<ResearchWorkspace[]>([]);
  const [activeWorkspaceId, setActiveWorkspaceId] = useState<string | null>(
    initialWorkspaceId ?? null,
  );
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const loadWorkspaces = useEffectEvent(async () => {
    setIsLoading(true);
    setError(null);
    try {
      const next = await researchBridge.listResearchWorkspaces();
      startTransition(() => {
        setWorkspaces(next);
        setActiveWorkspaceId((current) => current ?? next[0]?.id ?? null);
      });
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : String(loadError));
    } finally {
      setIsLoading(false);
    }
  });

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

  useResearchEventSubscriptions({
    onWorkspaceUpdate: ({ workspace }) => {
      startTransition(() => {
        setWorkspaces((current) => upsertWorkspaceRecord(current, workspace));
        setActiveWorkspaceId((current) => current ?? workspace.id);
      });
    },
  });

  const activeWorkspace = useMemo(
    () =>
      workspaces.find((workspace) => workspace.id === activeWorkspaceId) ??
      workspaces[0] ??
      null,
    [activeWorkspaceId, workspaces],
  );

  const selectWorkspace = (workspaceId: string) => {
    startTransition(() => {
      setActiveWorkspaceId(workspaceId);
    });
  };

  const createWorkspace = async (
    request: CreateResearchWorkspaceRequest,
  ): Promise<ResearchWorkspace> => {
    const workspace = await researchBridge.createResearchWorkspace(request);
    startTransition(() => {
      setWorkspaces((current) => upsertWorkspaceRecord(current, workspace));
      setActiveWorkspaceId(workspace.id);
    });
    return workspace;
  };

  const ensureWorkspaceForTicker = async (ticker: string): Promise<ResearchWorkspace> => {
    const normalizedTicker = ticker.trim().toUpperCase();
    const existing = workspaces.find(
      (workspace) => workspace.primaryTicker.toUpperCase() === normalizedTicker,
    );

    if (existing) {
      setActiveWorkspaceId(existing.id);
      return existing;
    }

    return createWorkspace({
      name: `${normalizedTicker} Research`,
      primaryTicker: normalizedTicker,
    });
  };

  const ensureWorkspace = async ({
    ticker,
    workspaceId,
  }: EnsureResearchWorkspaceRequest): Promise<ResearchWorkspace | null> => {
    if (workspaceId) {
      const existing = workspaces.find((workspace) => workspace.id === workspaceId) ?? null;
      if (existing) {
        setActiveWorkspaceId(existing.id);
      }
      return existing;
    }

    if (ticker) {
      return ensureWorkspaceForTicker(ticker);
    }

    const firstWorkspace = workspaces[0] ?? null;
    if (firstWorkspace) {
      setActiveWorkspaceId(firstWorkspace.id);
    }
    return firstWorkspace;
  };

  const ensureWorkspaceForIntent = async (
    intent: ResearchNavigationIntent,
  ): Promise<ResearchWorkspace | null> => {
    const ensured = await ensureWorkspace({
      workspaceId: intent.workspaceId,
      ticker: intent.ticker,
    });

    if (ensured && intent.preferredView && ensured.defaultView !== intent.preferredView) {
      return {
        ...ensured,
        defaultView: intent.preferredView,
      };
    }

    return ensured;
  };

  return {
    workspaces,
    activeWorkspace,
    activeWorkspaceId,
    isLoading,
    error,
    refreshWorkspaces: loadWorkspaces,
    selectWorkspace,
    createWorkspace,
    ensureWorkspace,
    ensureWorkspaceForTicker,
    ensureWorkspaceForIntent,
  };
};
