import { api } from "@code/backend/convex/_generated/api";
import type { Id } from "@code/backend/convex/_generated/dataModel";
import { useFlueAgent } from "@flue/react";
import { useQuery } from "convex/react";
import { useMemo, useState } from "react";

import { useChatAgent } from "@/hooks/chat/use-chat-agent";
import { usePersonalOrganization } from "@/hooks/use-personal-organization";
import { useProjectWorkspace } from "@/hooks/use-project-workspace";
import type { ChatAgentState } from "@/lib/chat/types";
import {
  buildWorkUnitCard,
  buildWorkUnitDetail,
  eventsForIssue,
} from "@/lib/work-os/work-unit-projection";
import type {
  LinkedSignal,
  WorkUnitCard,
  WorkUnitDetail,
} from "@/lib/work-os/work-unit-projection";

export interface SignalItem {
  readonly title: string;
  readonly summary: string;
  readonly sourceCount: number;
  readonly createdAt: number;
}

export type ComposerMode = "project" | "work-unit";

export interface WorkOsState {
  readonly projects: ReturnType<typeof useProjectWorkspace>["projects"];
  readonly selectedProject: ReturnType<
    typeof useProjectWorkspace
  >["selectedProject"];
  readonly selectedProjectId: ReturnType<
    typeof useProjectWorkspace
  >["selectedProjectId"];
  readonly repository: string;
  readonly setRepository: (value: string) => void;
  readonly connectRepository: () => Promise<void>;

  readonly workUnitCards: readonly WorkUnitCard[];
  readonly selectedIssue: ReturnType<
    typeof useProjectWorkspace
  >["selectedIssue"];
  readonly selectedIssueId: Id<"projectIssues"> | null;
  readonly selectedDetail: WorkUnitDetail | null;
  readonly selectIssue: (issueId: Id<"projectIssues"> | null) => void;
  readonly startIssue: ReturnType<typeof useProjectWorkspace>["startIssue"];
  readonly raiseIssue: ReturnType<typeof useProjectWorkspace>["raiseIssue"];
  readonly issueTitle: string;
  readonly setIssueTitle: (value: string) => void;
  readonly issueBody: string;
  readonly setIssueBody: (value: string) => void;

  readonly signals: readonly SignalItem[];

  readonly composerMode: ComposerMode;
  readonly setComposerMode: (mode: ComposerMode) => void;
  readonly projectAgent: ChatAgentState;
  readonly workUnitAgent: ChatAgentState;

  readonly pendingAction: string | null;
  readonly error: string | null;
}

const toLinkedSignals = (
  entries:
    | readonly {
        readonly signalId: Id<"signals">;
        readonly title: string;
        readonly summary: string;
        readonly sourceCount: number;
        readonly createdAt: number;
      }[]
    | undefined
): readonly LinkedSignal[] =>
  (entries ?? []).map((entry) => ({
    createdAt: entry.createdAt,
    signalId: entry.signalId,
    sourceCount: entry.sourceCount,
    summary: entry.summary,
    title: entry.title,
  }));

export const useWorkOs = (): WorkOsState => {
  const workspace = useProjectWorkspace();
  const orgState = usePersonalOrganization();
  const projectAgent = useChatAgent();

  const activeProjectId = workspace.selectedProjectId;

  const workUnitFlue = useFlueAgent({
    id: workspace.selectedIssueId
      ? String(workspace.selectedIssueId)
      : undefined,
    live: "sse",
    name: "project-manager",
  });
  const workUnitAgent: ChatAgentState = {
    error: workUnitFlue.error,
    historyReady: workUnitFlue.historyReady,
    messages: workUnitFlue.messages,
    sendMessage: workUnitFlue.sendMessage,
    status: workspace.selectedIssueId ? workUnitFlue.status : "idle",
  };

  // Project-level signals for the global sidebar panel.
  const allSignals = useQuery(
    api.signals.list,
    orgState.organizationId
      ? { organizationId: orgState.organizationId }
      : "skip"
  );
  const signals = useMemo<readonly SignalItem[]>(() => {
    if (!allSignals || !activeProjectId) {
      return [];
    }
    return allSignals
      .filter((entry) => entry.signal.projectId === activeProjectId)
      .map((entry) => ({
        createdAt: entry.signal.createdAt,
        sourceCount: entry.sources.length,
        summary: entry.signal.problemStatement.summary,
        title: entry.signal.problemStatement.title,
      }));
  }, [allSignals, activeProjectId]);

  // All linked signals for the active project, grouped by issue id.
  // Used for card counts and detail display.
  const linkedByIssue = useQuery(
    api.signals.listLinkedSignalsForProject,
    activeProjectId ? { projectId: activeProjectId } : "skip"
  );

  const [composerMode, setComposerMode] = useState<ComposerMode>("project");

  const selectIssue = (issueId: Id<"projectIssues"> | null) => {
    workspace.setSelectedIssueId(issueId);
    setComposerMode(issueId ? "work-unit" : "project");
  };

  const workUnitCards = useMemo<readonly WorkUnitCard[]>(() => {
    if (!workspace.issues) {
      return [];
    }
    return workspace.issues.map((issue) => {
      const issueEvents = eventsForIssue(workspace.events, issue._id);
      const linked = toLinkedSignals(linkedByIssue?.[String(issue._id)]);
      return buildWorkUnitCard({
        issue,
        issueEvents,
        linkedSignals: linked,
      });
    });
  }, [workspace.issues, workspace.events, linkedByIssue]);

  const selectedDetail = useMemo<WorkUnitDetail | null>(() => {
    if (!workspace.selectedIssue) {
      return null;
    }
    const issueEvents = eventsForIssue(
      workspace.events,
      workspace.selectedIssue._id
    );
    const linked = toLinkedSignals(
      linkedByIssue?.[String(workspace.selectedIssue._id)]
    );
    return buildWorkUnitDetail({
      issue: workspace.selectedIssue,
      issueEvents,
      linkedSignals: linked,
    });
  }, [workspace.selectedIssue, workspace.events, linkedByIssue]);

  return {
    composerMode,
    connectRepository: workspace.connectRepository,
    error: workspace.error,
    issueBody: workspace.issueBody,
    issueTitle: workspace.issueTitle,
    pendingAction: workspace.pendingAction,
    projectAgent,
    projects: workspace.projects,
    raiseIssue: workspace.raiseIssue,
    repository: workspace.repository,
    selectIssue,
    selectedDetail,
    selectedIssue: workspace.selectedIssue,
    selectedIssueId: workspace.selectedIssueId,
    selectedProject: workspace.selectedProject,
    selectedProjectId: activeProjectId,
    setComposerMode,
    setIssueBody: workspace.setIssueBody,
    setIssueTitle: workspace.setIssueTitle,
    setRepository: workspace.setRepository,
    signals,
    startIssue: workspace.startIssue,
    workUnitAgent,
    workUnitCards,
  };
};
