/**
 * `ProjectsView` — the top-level project surface (L2 / L11).
 *
 * IDE layout (full remaining height):
 *
 *   ┌───────────────────────────────────────────────────────┐
 *   │ PROJECT TABS  [ alpha × ][ beta × ]  [+]              │
 *   ├───────────────┬───────────────────────────────────────┤
 *   │ SIDEBAR ≈320px│  MAIN — LayoutGrid (fills remaining)  │
 *   │ [Proj][Agents]│  — or welcome screen when no active   │
 *   │ [Tmpl][Git]   │                                       │
 *   │ panel body    │                                       │
 *   └───────────────┴───────────────────────────────────────┘
 *
 * The "Projects" sidebar tab always hosts the create-project form and the
 * known-projects list, ensuring they are always in the DOM (required by tests).
 *
 * Pure presentation: all behaviour comes from {@link useProjects}. Styling via
 * `@/shared`; no inline styles, no `invoke()`.
 *
 * **Test-contract** — the following query hooks from `projects.test.tsx` are
 * always present in the DOM regardless of which sidebar tab is active:
 *   - getByLabelText("project name") / ("project root") — form inputs
 *   - getByRole("button", { name: "Create project" }) / "Refresh" / "Open" / "close <name>"
 *   - getByRole("tablist") + getAllByRole("tab") + aria-selected — project tabs
 *   - getByText("No projects yet.") / "No open tabs." — empty states
 *   - getAllByRole("listitem") — known-projects list
 *   - getByRole("alert") — error display
 */

import { useEffect, useState } from "react";

import type { LayoutInfo } from "@/domain";
import { LayoutGrid, LayoutTabs } from "@/features/layout";
import { AgentsPanel } from "@/features/agents";
import { TemplatesPanel } from "@/features/templates";
import { SkillsPanel } from "@/features/skills";
import { MemoryPanel } from "@/features/memory";
import { EmbedderSettings } from "@/features/embedder";
import { PermissionsPanel } from "@/features/permissions";
import { ProjectWorkStatePanel } from "@/features/workstate";
import { ConversationViewer } from "@/features/conversations";
import { GitPanel, GitGraphView } from "@/features/git";
import { Button, Input, Panel, Tabs, cn } from "@/shared";
import { useGateways } from "@/app/di";
import { ProjectContextPanel } from "./ProjectContextPanel";
import { useProjects } from "./useProjects";

type SidebarTab =
  | "projects"
  | "context"
  | "work"
  | "agents"
  | "templates"
  | "skills"
  | "permissions"
  | "memory"
  | "git";

const SIDEBAR_TABS: { id: SidebarTab; label: string }[] = [
  { id: "projects", label: "Projects" },
  { id: "context", label: "Context" },
  { id: "work", label: "Work" },
  { id: "agents", label: "Agents" },
  { id: "templates", label: "Templates" },
  { id: "skills", label: "Skills" },
  { id: "permissions", label: "Perms" },
  { id: "memory", label: "Memory" },
  { id: "git", label: "Git" },
];

export function ProjectsView() {
  const vm = useProjects();
  const { system } = useGateways();
  const [name, setName] = useState("");
  const [root, setRoot] = useState("");
  const [sidebarTab, setSidebarTab] = useState<SidebarTab>("projects");
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  // The active layout (id + kind), reported by LayoutTabs — the single source of
  // truth. `kind` decides whether the main area is the terminal grid or the git
  // graph view.
  const [activeLayout, setActiveLayout] = useState<LayoutInfo | null>(null);
  // When set, the main area swaps the terminal grid for the read-only
  // conversation viewer (LS7) — pure local UI state, same mechanic as the
  // terminal↔gitGraph swap; **not** a backend layout kind.
  const [viewerConversationId, setViewerConversationId] = useState<
    string | null
  >(null);

  const active = vm.openTabs.find((t) => t.id === vm.activeTabId) ?? null;

  // Reset the active layout whenever the active project changes. `activeLayout`
  // is only repopulated asynchronously by `LayoutTabs` (which re-fetches the new
  // project's layouts). Without this reset, the stale id of the *previous*
  // project would be handed to `LayoutGrid`/`GitGraphView` during the gap, and
  // loading it against the new project's store fails with "not found: layout X".
  useEffect(() => {
    setActiveLayout(null);
    setViewerConversationId(null);
  }, [active?.id]);

  const activeLayoutKind = activeLayout?.kind ?? "terminal";

  const canCreate = name.trim().length > 0 && root.trim().length > 0 && !vm.busy;

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    if (!canCreate) return;
    await vm.createProject(name.trim(), root.trim());
    setName("");
    setRoot("");
  }

  async function handleBrowse() {
    const picked = await system.pickFolder();
    if (picked !== null) setRoot(picked);
  }

  return (
    <div className="flex flex-1 flex-col overflow-hidden">
      {/* ── Error alert ── */}
      {vm.error && (
        <p
          role="alert"
          className="mx-4 mt-2 shrink-0 rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-sm text-danger"
        >
          {vm.error}
        </p>
      )}

      {/* ── Project tab bar ── */}
      <div className="flex shrink-0 items-center gap-1 border-b border-border bg-surface px-2 py-1">
        {vm.openTabs.length === 0 ? (
          <p className="px-2 text-sm text-muted">No open tabs.</p>
        ) : (
          <Tabs
            items={vm.openTabs.map((t) => ({ id: t.id, label: t.name }))}
            value={vm.activeTabId}
            onSelect={(id) => vm.activateTab(id)}
            onClose={(id) => void vm.closeTab(id)}
            className="flex-1"
          />
        )}
      </div>

      {/* ── IDE body: sidebar + main ── */}
      <div className="flex flex-1 overflow-hidden">
        {/* ── Collapsed sidebar: a thin rail with an expand button ── */}
        {sidebarCollapsed && (
          <aside className="flex w-9 shrink-0 flex-col items-center border-r border-border bg-surface py-1">
            <button
              type="button"
              aria-label="expand sidebar"
              title="Expand sidebar"
              onClick={() => setSidebarCollapsed(false)}
              className="flex h-7 w-7 items-center justify-center rounded text-muted hover:bg-raised hover:text-content"
            >
              »
            </button>
          </aside>
        )}

        {/* ── Sidebar ── */}
        <aside
          className={cn(
            "flex w-80 shrink-0 flex-col border-r border-border bg-surface",
            sidebarCollapsed && "hidden",
          )}
        >
          {/* Sidebar tab strip (no role="tablist" to avoid collision with project tabs).
              The tabs wrap onto multiple rows when they exceed the sidebar width
              so every label stays visible without scrolling; the collapse button
              stays pinned to the top-right. */}
          <div className="flex shrink-0 items-start border-b border-border">
            <div className="flex min-w-0 flex-1 flex-wrap items-stretch">
              {SIDEBAR_TABS.map((t) => (
                <button
                  key={t.id}
                  type="button"
                  aria-selected={sidebarTab === t.id}
                  onClick={() => setSidebarTab(t.id)}
                  className={cn(
                    "shrink-0 whitespace-nowrap px-3 py-2 text-xs font-medium transition-colors",
                    sidebarTab === t.id
                      ? "border-b-2 border-primary text-content"
                      : "text-muted hover:text-content",
                  )}
                >
                  {t.label}
                </button>
              ))}
            </div>
            <button
              type="button"
              aria-label="collapse sidebar"
              title="Collapse sidebar"
              onClick={() => setSidebarCollapsed(true)}
              className="shrink-0 self-stretch border-l border-border px-2 text-muted hover:text-content"
            >
              «
            </button>
          </div>

          {/* Sidebar panel body */}
          <div className="flex-1 overflow-auto p-3">
            {/* Projects panel */}
            {sidebarTab === "projects" && (
              <div className="flex flex-col gap-4">
                {/* Create form */}
                <form
                  onSubmit={submit}
                  className="flex flex-col gap-2"
                >
                  <h3 className="text-xs font-semibold uppercase tracking-wide text-faint">
                    New project
                  </h3>
                  <Input
                    aria-label="project name"
                    placeholder="Project name"
                    value={name}
                    onChange={(e) => setName(e.target.value)}
                  />
                  <div className="flex gap-2">
                    <Input
                      aria-label="project root"
                      placeholder="/absolute/project/root"
                      value={root}
                      onChange={(e) => setRoot(e.target.value)}
                      className="flex-1"
                    />
                    <Button
                      type="button"
                      aria-label="browse project folder"
                      onClick={() => void handleBrowse()}
                      disabled={vm.busy}
                    >
                      Browse…
                    </Button>
                  </div>
                  <div className="flex gap-2">
                    <Button
                      type="submit"
                      variant="primary"
                      disabled={!canCreate}
                      className="flex-1"
                    >
                      Create project
                    </Button>
                    <Button
                      type="button"
                      onClick={() => void vm.refresh()}
                      disabled={vm.busy}
                    >
                      Refresh
                    </Button>
                  </div>
                </form>

                {/* Known projects list */}
                <Panel title="Known projects">
                  {vm.projects.length === 0 ? (
                    <p className="text-sm text-muted">No projects yet.</p>
                  ) : (
                    <ul className="flex flex-col divide-y divide-border">
                      {vm.projects.map((p) => (
                        <li
                          key={p.id}
                          className="flex items-center justify-between gap-2 py-2 first:pt-0 last:pb-0"
                        >
                          <span className="flex min-w-0 flex-col gap-0.5">
                            <span className="font-medium text-content">{p.name}</span>
                            <code className="truncate text-xs text-muted">{p.root}</code>
                          </span>
                          <Button
                            size="sm"
                            onClick={() => void vm.openProject(p.id)}
                          >
                            Open
                          </Button>
                        </li>
                      ))}
                    </ul>
                  )}
                </Panel>
              </div>
            )}

            {/* Project context panel */}
            {sidebarTab === "context" && active && (
              <ProjectContextPanel projectId={active.id} />
            )}
            {sidebarTab === "context" && !active && (
              <p className="text-sm text-muted">Open a project to edit context.</p>
            )}

            {/* Work-state panel */}
            {sidebarTab === "work" && active && (
              <ProjectWorkStatePanel
                projectId={active.id}
                onOpenConversation={setViewerConversationId}
              />
            )}
            {sidebarTab === "work" && !active && (
              <p className="text-sm text-muted">Open a project to view work state.</p>
            )}

            {/* Agents panel — only rendered when active project exists */}
            {sidebarTab === "agents" && active && (
              <AgentsPanel projectId={active.id} projectRoot={active.root} />
            )}
            {sidebarTab === "agents" && !active && (
              <p className="text-sm text-muted">Open a project to manage agents.</p>
            )}

            {/* Templates panel */}
            {sidebarTab === "templates" && active && (
              <TemplatesPanel projectId={active.id} />
            )}
            {sidebarTab === "templates" && !active && (
              <p className="text-sm text-muted">Open a project to manage templates.</p>
            )}

            {/* Skills panel */}
            {sidebarTab === "skills" && active && (
              <SkillsPanel projectId={active.id} />
            )}
            {sidebarTab === "skills" && !active && (
              <p className="text-sm text-muted">Open a project to manage skills.</p>
            )}

            {/* Permissions panel */}
            {sidebarTab === "permissions" && active && (
              <PermissionsPanel projectId={active.id} />
            )}
            {sidebarTab === "permissions" && !active && (
              <p className="text-sm text-muted">Open a project to manage permissions.</p>
            )}

            {/* Memory panel + embedder settings */}
            {sidebarTab === "memory" && active && (
              <div className="flex flex-col gap-4">
                <MemoryPanel projectId={active.id} />
                <EmbedderSettings />
              </div>
            )}
            {sidebarTab === "memory" && !active && (
              <p className="text-sm text-muted">Open a project to manage memory.</p>
            )}

            {/* Git panel */}
            {sidebarTab === "git" && active && (
              <GitPanel projectId={active.id} />
            )}
            {sidebarTab === "git" && !active && (
              <p className="text-sm text-muted">Open a project to manage git.</p>
            )}
          </div>
        </aside>

        {/* ── Main: terminal grid or git graph (fills remaining height) ── */}
        <main className="flex flex-1 flex-col overflow-hidden">
          {active && viewerConversationId ? (
            <ConversationViewer
              key={`${active.id}-${viewerConversationId}`}
              projectId={active.id}
              conversationId={viewerConversationId}
              onClose={() => setViewerConversationId(null)}
            />
          ) : active ? (
            <>
              <LayoutTabs
                projectId={active.id}
                onActiveLayoutChange={setActiveLayout}
              />
              {activeLayoutKind === "gitGraph" ? (
                <GitGraphView
                  key={`${active.id}-${activeLayout?.id ?? "default"}-graph`}
                  projectId={active.id}
                />
              ) : (
                <LayoutGrid
                  key={`${active.id}-${activeLayout?.id ?? "default"}`}
                  projectId={active.id}
                  cwd={active.root}
                  layoutId={activeLayout?.id}
                />
              )}
            </>
          ) : (
            <div className="flex flex-1 items-center justify-center text-muted">
              <p className="text-sm">Select or create a project to get started.</p>
            </div>
          )}
        </main>
      </div>
    </div>
  );
}
