/**
 * `GitPanel` — feature component for the Git panel (L8).
 *
 * Shows the working-tree status grouped by Staged / Unstaged, a commit form,
 * branch management with checkout, and the recent commit log.
 *
 * Pure presentation: all behaviour comes from {@link useGit}. Styled with
 * `@/shared`; no inline styles.
 */

import { useState } from "react";

import { Button, Input, Panel, Spinner, cn } from "@/shared";
import { useGit } from "./useGit";
import { buildFileTree, type GitTreeNode } from "./gitTree";

/**
 * Recursively renders a changed-files tree. Directories are static rows; file
 * leaves carry the stage/unstage action (its `aria-label` uses the full path).
 */
function FileTree({
  nodes,
  depth,
  action,
  onAction,
  busy,
}: {
  nodes: GitTreeNode[];
  depth: number;
  action: "stage" | "unstage";
  onAction: (path: string) => void;
  busy: boolean;
}) {
  return (
    <ul className="flex flex-col gap-0.5">
      {nodes.map((node) =>
        node.isDir ? (
          <li key={node.path}>
            <div
              className="flex items-center gap-1 px-2 py-0.5 text-xs text-muted"
              style={{ paddingLeft: `${depth * 14 + 8}px` }}
            >
              <span aria-hidden className="text-faint">
                ▸
              </span>
              <span className="truncate">{node.name}</span>
            </div>
            <FileTree
              nodes={node.children}
              depth={depth + 1}
              action={action}
              onAction={onAction}
              busy={busy}
            />
          </li>
        ) : (
          <li
            key={node.path}
            className="flex items-center justify-between gap-2 rounded-md px-2 py-1 hover:bg-raised"
            style={{ paddingLeft: `${depth * 14 + 8}px` }}
          >
            <span className="flex min-w-0 items-center gap-1.5">
              <span
                aria-hidden
                className={cn(
                  "size-1.5 shrink-0 rounded-full",
                  action === "unstage" ? "bg-success" : "bg-warning",
                )}
              />
              <code className="min-w-0 truncate text-xs text-content">
                {node.name}
              </code>
            </span>
            <Button
              size="sm"
              variant="ghost"
              aria-label={`${action} ${node.path}`}
              disabled={busy}
              onClick={() => onAction(node.path)}
              className="shrink-0 text-muted hover:text-content"
            >
              {action === "unstage" ? "Unstage" : "Stage"}
            </Button>
          </li>
        ),
      )}
    </ul>
  );
}

export interface GitPanelProps {
  /** The project whose git state to manage. */
  projectId: string;
}

export function GitPanel({ projectId }: GitPanelProps) {
  const vm = useGit(projectId);
  const [commitMessage, setCommitMessage] = useState("");
  const [newBranch, setNewBranch] = useState("");

  const staged = vm.files.filter((f) => f.staged);
  const unstaged = vm.files.filter((f) => !f.staged);
  const canCommit = commitMessage.trim().length > 0 && staged.length > 0 && !vm.busy;

  async function handleCommit(e: React.FormEvent) {
    e.preventDefault();
    if (!canCommit) return;
    await vm.commit(commitMessage.trim());
    setCommitMessage("");
  }

  async function handleCheckout(branch: string) {
    await vm.checkout(branch);
  }

  async function handleNewBranch(e: React.FormEvent) {
    e.preventDefault();
    const b = newBranch.trim();
    if (!b || vm.busy) return;
    await vm.checkout(b);
    setNewBranch("");
  }

  return (
    <Panel title="Git" className="flex flex-col gap-0">
      {vm.error && (
        <p
          role="alert"
          className="mx-4 mt-3 rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-sm text-danger"
        >
          {vm.error}
        </p>
      )}

      {/* ── Changes ── */}
      <section aria-label="Changes" className="border-b border-border p-4">
        <div className="mb-2 flex items-center justify-between gap-2">
          <h4 className="text-xs font-semibold uppercase tracking-wide text-faint">
            Changes
          </h4>
          {vm.busy && <Spinner size={12} />}
        </div>

        {vm.files.length === 0 ? (
          <p className="text-sm text-muted">No changes.</p>
        ) : (
          <div className="flex flex-col gap-3">
            {/* Staged — shown as a file tree. */}
            {staged.length > 0 && (
              <div>
                <p className="mb-1 text-xs font-medium text-muted">Staged</p>
                <FileTree
                  nodes={buildFileTree(staged)}
                  depth={0}
                  action="unstage"
                  onAction={(p) => void vm.unstage(p)}
                  busy={vm.busy}
                />
              </div>
            )}

            {/* Unstaged — shown as a file tree. */}
            {unstaged.length > 0 && (
              <div>
                <p className="mb-1 text-xs font-medium text-muted">Unstaged</p>
                <FileTree
                  nodes={buildFileTree(unstaged)}
                  depth={0}
                  action="stage"
                  onAction={(p) => void vm.stage(p)}
                  busy={vm.busy}
                />
              </div>
            )}
          </div>
        )}
      </section>

      {/* ── Commit ── */}
      <section aria-label="Commit" className="border-b border-border p-4">
        <h4 className="mb-2 text-xs font-semibold uppercase tracking-wide text-faint">
          Commit
        </h4>
        <form onSubmit={handleCommit} className="flex flex-col gap-2">
          <Input
            aria-label="commit message"
            placeholder="Commit message"
            value={commitMessage}
            onChange={(e) => setCommitMessage(e.target.value)}
          />
          <Button
            type="submit"
            variant="primary"
            disabled={!canCommit}
            loading={vm.busy}
            className="self-end"
          >
            Commit
          </Button>
        </form>
      </section>

      {/* ── Branches ── */}
      <section aria-label="Branches" className="border-b border-border p-4">
        <h4 className="mb-2 text-xs font-semibold uppercase tracking-wide text-faint">
          Branches
        </h4>
        <p className="mb-2 text-sm text-content">
          Current:{" "}
          <span className="font-medium">
            {vm.branches.current ?? "(none)"}
          </span>
        </p>

        {vm.branches.branches.length > 0 && (
          <ul className="mb-3 flex flex-col gap-0.5">
            {vm.branches.branches.map((b) => {
              const isCurrent = b === vm.branches.current;
              return (
                <li
                  key={b}
                  className={cn(
                    "flex items-center justify-between gap-2 rounded-md px-2 py-1",
                    isCurrent && "bg-raised",
                  )}
                >
                  <span
                    className={cn(
                      "text-sm",
                      isCurrent ? "font-semibold text-primary" : "text-content",
                    )}
                  >
                    {b}
                  </span>
                  {!isCurrent && (
                    <Button
                      size="sm"
                      variant="ghost"
                      aria-label={`checkout ${b}`}
                      disabled={vm.busy}
                      onClick={() => void handleCheckout(b)}
                      className="shrink-0 text-muted hover:text-content"
                    >
                      Checkout
                    </Button>
                  )}
                </li>
              );
            })}
          </ul>
        )}

        <form onSubmit={handleNewBranch} className="flex items-center gap-2">
          <Input
            aria-label="new branch name"
            placeholder="New branch"
            value={newBranch}
            onChange={(e) => setNewBranch(e.target.value)}
            className="flex-1"
          />
          <Button
            type="submit"
            variant="ghost"
            disabled={!newBranch.trim() || vm.busy}
          >
            Create &amp; checkout
          </Button>
        </form>
      </section>

      {/* ── Log ── */}
      <section aria-label="Log" className="p-4">
        <h4 className="mb-2 text-xs font-semibold uppercase tracking-wide text-faint">
          Log
        </h4>
        {vm.log.length === 0 ? (
          <p className="text-sm text-muted">No commits yet.</p>
        ) : (
          <ul className="flex flex-col divide-y divide-border">
            {vm.log.map((c) => (
              <li key={c.hash} className="flex items-baseline gap-2 py-1.5">
                <code className="shrink-0 text-xs text-faint">
                  {c.hash.slice(0, 7)}
                </code>
                <span className="min-w-0 truncate text-sm text-content">
                  {c.summary}
                </span>
              </li>
            ))}
          </ul>
        )}
      </section>
    </Panel>
  );
}
