import { CircleAlert, GitFork, LoaderCircle, Plus } from "lucide-react";
import { useState } from "react";

import { ConversationPanel } from "@/components/work-os/conversation-panel";
import { EmptyState } from "@/components/work-os/empty-state";
import { SignalsPanel } from "@/components/work-os/signals-panel";
import { WorkOsComposer } from "@/components/work-os/work-os-composer";
import { WorkOsHeader } from "@/components/work-os/work-os-header";
import { WorkUnitCard } from "@/components/work-os/work-unit-card";
import { WorkUnitDetail } from "@/components/work-os/work-unit-detail";
import { useWorkOs } from "@/hooks/work-os/use-work-os";
import type { WorkOsState } from "@/hooks/work-os/use-work-os";

type CardData = WorkOsState["workUnitCards"][number];
type IssueId = WorkOsState["selectedIssueId"];

interface ProjectOption {
  readonly host?: string;
  readonly id: string;
  readonly name: string;
}

const toProjectOption = (project: {
  readonly id: string;
  readonly name: string;
  readonly sources: readonly { readonly host?: string }[];
}): ProjectOption => ({
  host: project.sources[0]?.host,
  id: project.id,
  name: project.name,
});

const LoadingLine = ({ label }: { readonly label: string }) => (
  <div className="flex items-center gap-2 text-xs text-muted-foreground">
    <LoaderCircle className="size-3.5 animate-spin" />
    {label}
  </div>
);

const isAgentBusy = (status: string): boolean =>
  status === "connecting" || status === "submitted" || status === "streaming";

const CONVERSATION_COPY = {
  projectHint:
    "Describe what you want Zopu to work on. Work Units created from the conversation will appear in the right panel.",
  projectTitle: "Project conversation",
  workUnitHint:
    "Send a message to continue this Work Unit. The project manager agent will pick up the existing context.",
  workUnitTitle: "Work Unit conversation",
} as const;

interface IssueComposerProps {
  readonly body: string;
  readonly busy: boolean;
  readonly onBodyChange: (value: string) => void;
  readonly onSubmit: () => void;
  readonly onTitleChange: (value: string) => void;
  readonly title: string;
}

const IssueComposer = ({
  body,
  busy,
  onBodyChange,
  onSubmit,
  onTitleChange,
  title,
}: IssueComposerProps) => (
  <form
    className="rounded-2xl border border-border/40 bg-card/40 p-4"
    onSubmit={(event) => {
      event.preventDefault();
      onSubmit();
    }}
  >
    <div className="mb-3 flex items-center gap-2">
      <div className="grid size-7 place-items-center rounded-lg bg-foreground text-background">
        <Plus className="size-3.5" />
      </div>
      <p className="text-sm font-semibold">Create a Work Unit</p>
    </div>
    <div className="space-y-2">
      <input
        aria-label="Work Unit title"
        className="w-full rounded-xl border border-border/40 bg-background/40 px-3 py-2 text-sm outline-none placeholder:text-muted-foreground/60 focus-visible:border-foreground/20"
        onChange={(event) => onTitleChange(event.target.value)}
        placeholder="Outcome title"
        required
        value={title}
      />
      <textarea
        aria-label="Work Unit description"
        className="min-h-20 w-full resize-none rounded-xl border border-border/40 bg-background/40 px-3 py-2 text-sm outline-none placeholder:text-muted-foreground/60 focus-visible:border-foreground/20"
        onChange={(event) => onBodyChange(event.target.value)}
        placeholder="Describe the desired result, constraints, or evidence."
        required
        rows={3}
        value={body}
      />
    </div>
    <button
      className="mt-3 inline-flex items-center gap-2 rounded-xl bg-foreground px-4 py-2 text-sm font-medium text-background transition-opacity hover:opacity-90 disabled:opacity-60"
      disabled={busy}
      type="submit"
    >
      {busy ? (
        <LoaderCircle className="size-4 animate-spin" />
      ) : (
        <Plus className="size-4" />
      )}
      {busy ? "Creating" : "Create Work Unit"}
    </button>
  </form>
);

const WorkUnitCards = ({
  cards,
  onSelect,
  selectedId,
}: {
  readonly cards: readonly CardData[];
  readonly onSelect: (issueId: IssueId) => void;
  readonly selectedId: IssueId;
}) => {
  if (cards.length === 0) {
    return (
      <div className="rounded-2xl border border-dashed border-border/40 p-6 text-center">
        <GitFork className="mx-auto size-4 text-muted-foreground" />
        <p className="mt-2 text-sm font-medium">No Work Units yet</p>
        <p className="mt-1 text-xs text-muted-foreground">
          Create one above, or describe what you need in the conversation.
        </p>
      </div>
    );
  }
  return (
    <div className="space-y-2">
      {cards.map((card) => (
        <WorkUnitCard
          card={card}
          key={card.issueId}
          onSelect={() => onSelect(card.issueId)}
          selected={selectedId === card.issueId}
        />
      ))}
    </div>
  );
};

const MobileWorkUnitList = ({
  cards,
  onSelect,
  selectedId,
}: {
  readonly cards: readonly CardData[];
  readonly onSelect: (issueId: IssueId) => void;
  readonly selectedId: IssueId;
}) => {
  if (cards.length === 0) {
    return (
      <div className="rounded-2xl border border-dashed border-border/40 p-4 text-center">
        <p className="text-xs text-muted-foreground">
          No Work Units yet. Create one or chat with Zopu.
        </p>
      </div>
    );
  }
  return (
    <div className="space-y-2">
      {cards.map((card) => (
        <WorkUnitCard
          card={card}
          key={card.issueId}
          onSelect={() => onSelect(card.issueId)}
          selected={selectedId === card.issueId}
        />
      ))}
    </div>
  );
};

interface NoProjectProps {
  readonly busy: boolean;
  readonly onConnectRepository: () => Promise<void>;
  readonly onRepositoryChange: (value: string) => void;
  readonly projects: WorkOsState["projects"];
  readonly repository: string;
}

const NoProjectView = ({
  busy,
  onConnectRepository,
  onRepositoryChange,
  projects,
  repository,
}: NoProjectProps) => {
  if (projects === undefined) {
    return (
      <div className="grid h-full place-items-center">
        <LoadingLine label="Loading projects" />
      </div>
    );
  }
  return (
    <EmptyState
      busy={busy}
      onConnectRepository={onConnectRepository}
      onRepositoryChange={onRepositoryChange}
      repository={repository}
    />
  );
};

export const WorkOsPage = () => {
  const os = useWorkOs();
  const [mobileDetailOpen, setMobileDetailOpen] = useState(false);
  const [issueTitle, setIssueTitle] = useState("");
  const [issueBody, setIssueBody] = useState("");

  const handleSelectIssue = (issueId: IssueId) => {
    os.selectIssue(issueId);
    setMobileDetailOpen(issueId !== null);
  };

  const handleStart = () => {
    if (!os.selectedIssue) {
      return;
    }
    void os.startIssue(
      os.selectedIssue._id,
      os.selectedIssue.number,
      os.selectedIssue.title
    );
  };

  const handleRaiseIssue = () => {
    void os.raiseIssue({ body: issueBody, title: issueTitle });
    setIssueTitle("");
    setIssueBody("");
  };

  const handleSend = (message: string): Promise<void> =>
    os.composerMode === "work-unit" && os.selectedIssueId
      ? os.workUnitAgent.sendMessage(message)
      : os.projectAgent.sendMessage(message);

  const handleModeChange = (mode: "project" | "work-unit") =>
    os.setComposerMode(mode);
  const handleConnectRepository = os.connectRepository;
  const handleRepositoryChange = os.setRepository;

  const isWorkUnitMode =
    os.composerMode === "work-unit" && !!os.selectedIssueId;
  const activeAgent = isWorkUnitMode ? os.workUnitAgent : os.projectAgent;
  const conversationTitle = isWorkUnitMode
    ? CONVERSATION_COPY.workUnitTitle
    : CONVERSATION_COPY.projectTitle;
  const conversationHint = isWorkUnitMode
    ? CONVERSATION_COPY.workUnitHint
    : CONVERSATION_COPY.projectHint;

  const selectedProjectOption = os.selectedProject
    ? toProjectOption(os.selectedProject)
    : null;
  const projectOptions = os.projects?.map(toProjectOption) ?? undefined;
  const cards = os.workUnitCards ?? [];
  const startPending = os.pendingAction === `issue:${os.selectedIssue?._id}`;
  const showConversation = !(mobileDetailOpen && os.selectedDetail);

  return (
    <div className="flex h-svh flex-col bg-background text-foreground">
      <WorkOsHeader
        connected={!!os.selectedProject}
        onBack={() => {
          os.selectIssue(null);
          setMobileDetailOpen(false);
        }}
        onSelectProject={() => os.selectIssue(null)}
        projects={projectOptions}
        selectedProject={selectedProjectOption}
        showBack={mobileDetailOpen && !!os.selectedIssue}
      />

      {os.error ? (
        <div className="flex items-start gap-3 border-b border-destructive/30 bg-destructive/10 px-4 py-2 text-sm text-destructive">
          <CircleAlert className="mt-0.5 size-4 shrink-0" />
          <p>{os.error}</p>
        </div>
      ) : null}

      {os.selectedProject ? (
        <main className="flex min-h-0 flex-1">
          {/* Left column: conversation + composer */}
          <div className="flex min-w-0 flex-1 flex-col">
            <div
              className={`min-h-0 flex-1 ${showConversation ? "block" : "hidden md:block"}`}
            >
              <ConversationPanel
                agent={activeAgent}
                emptyHint={conversationHint}
                title={conversationTitle}
              />
            </div>

            {/* Mobile: detail overlay */}
            {mobileDetailOpen && os.selectedDetail ? (
              <div className="min-h-0 flex-1 overflow-y-auto md:hidden">
                <WorkUnitDetail
                  detail={os.selectedDetail}
                  onOpenPullRequest={(url) =>
                    window.open(url, "_blank", "noopener,noreferrer")
                  }
                  onStart={handleStart}
                  startPending={startPending}
                />
              </div>
            ) : null}

            <WorkOsComposer
              busy={isAgentBusy(activeAgent.status)}
              error={
                os.composerMode === "work-unit"
                  ? os.workUnitAgent.error
                  : os.projectAgent.error
              }
              mode={os.composerMode}
              onModeChange={handleModeChange}
              onSend={handleSend}
              workUnitTitle={os.selectedIssue?.title}
            />
          </div>

          {/* Right column: Work Units, signals, detail */}
          <aside className="hidden w-[400px] shrink-0 flex-col overflow-y-auto border-l border-border/40 bg-background/50 p-4 md:flex lg:w-[440px]">
            <IssueComposer
              body={issueBody}
              busy={os.pendingAction === "issue"}
              onBodyChange={setIssueBody}
              onSubmit={handleRaiseIssue}
              onTitleChange={setIssueTitle}
              title={issueTitle}
            />

            <div className="mt-4">
              <SignalsPanel
                loading={os.signals === undefined}
                signals={os.signals}
              />
            </div>

            {os.selectedDetail ? (
              <div className="mt-4">
                <WorkUnitDetail
                  detail={os.selectedDetail}
                  onOpenPullRequest={(url) =>
                    window.open(url, "_blank", "noopener,noreferrer")
                  }
                  onStart={handleStart}
                  startPending={startPending}
                />
              </div>
            ) : null}

            <div className="mt-4">
              <p className="mb-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
                Work Units
              </p>
              <WorkUnitCards
                cards={cards}
                onSelect={handleSelectIssue}
                selectedId={os.selectedIssueId}
              />
            </div>
          </aside>

          {/* Mobile: Work Unit cards list */}
          <div className="border-t border-border/40 p-4 md:hidden">
            <p className="mb-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
              Work Units
            </p>
            <MobileWorkUnitList
              cards={cards}
              onSelect={handleSelectIssue}
              selectedId={os.selectedIssueId}
            />
          </div>
        </main>
      ) : (
        <main className="flex-1 overflow-y-auto">
          <NoProjectView
            busy={os.pendingAction === "connect"}
            onConnectRepository={handleConnectRepository}
            onRepositoryChange={handleRepositoryChange}
            projects={os.projects}
            repository={os.repository}
          />
        </main>
      )}
    </div>
  );
};
