/* Parley — the three record screens that are not the conversation: projects,
   the prompt library and the workspace files. Commit model: INSTANT on all
   three (no Save button anywhere; each control confirms itself, consequential
   ones raise an undo toast from App.jsx, irreversible ones open a confirm
   dialog there). Same architecture on each: filter bar, then the display, then
   the footer line that says what the display is showing. */
(() => {
  const {
    Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardPanel, CardFooter,
    Table, TableHeader, TableBody, TableRow, TableHead, TableCell,
    MenuItem, Separator, Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription, EmptyContent,
  } = window.OriginDesignSystem_7c998b;

  /* Two column stacks rather than an auto-fitting grid, so at one column the
     cards concatenate in reading order (AGENTS §5.1). */
  const intoColumns = (items, n) => {
    const columns = [];
    for (let i = 0; i < n; i++) columns.push([]);
    items.forEach((item, i) => columns[i % n].push(item));
    return columns;
  };

  /* ── Projects ──────────────────────────────────────────────────────── */

  function ProjectCard({ project, data, onNavigate, onRun }) {
    const threads = threadsInProject(data.threads, project.id);
    const files = filesInProject(data.files, project.id);
    const stuck = files.filter(FILE_FLAGS.needsAttention);
    const to = resolvePath("/projects/:id", { id: project.id });
    const archived = PROJECT_FLAGS.isArchived(project);
    return (
      <Card className={archived ? "pl-row--recessed" : undefined}>
        <div className="pl-project">
          <div className="pl-project__top">
            <button type="button" className="pl-project__name pl-link" onClick={() => onNavigate(to)}>{project.name}</button>
            <span className="pl-chips">
              {archived ? <Badge size="sm" variant="secondary">Archived</Badge> : <VisibilityBadge value={project.visibility} />}
              <RowActions transitions={projectTransitions(project)} onRun={(t) => onRun(project, t)} label={"Actions for " + project.name} />
            </span>
          </div>
          <p className="pl-project__purpose">{project.purpose}</p>
          <div className="pl-project__foot">
            <span>{threads.length} {threads.length === 1 ? "thread" : "threads"}</span>
            <span>{files.length} {files.length === 1 ? "file" : "files"}</span>
            {stuck.length ? <span style={{ color: "var(--warning-foreground)" }}>{stuck.length} the index could not read</span> : null}
            {archived
              ? <span>Archived {formatAge(project.archivedAt, data.now)}</span>
              : <span>{threads.length ? "Last reply " + formatAge(Math.max.apply(null, threads.map((t) => THREAD_FLAGS.lastActivityAt(t))), data.now) : "No threads yet"}</span>}
          </div>
        </div>
      </Card>
    );
  }

  function ProjectsScreen({ data, onNavigate, onRun, onNew }) {
    const [query, setQuery] = React.useState("");
    const [shelf, setShelf] = React.useState("live");
    const matched = data.projects.filter((p) => {
      if (shelf === "live" && PROJECT_FLAGS.isArchived(p)) return false;
      if (shelf === "archived" && !PROJECT_FLAGS.isArchived(p)) return false;
      return (p.name + " " + p.purpose).toLowerCase().indexOf(query.toLowerCase().trim()) > -1;
    });
    const dirty = query.trim().length > 0 || shelf !== "live";
    const clear = () => { setQuery(""); setShelf("live"); };
    /* Three branches, one at a time: nothing here at all, nothing matching the
       filters, or the projects. */
    if (!data.projects.length) {
      return (
        <div className="pl-page">
          <PageHead title="Projects" note="A project holds its own instructions and its own files, and every thread inside it is sent both." />
          <Card>
            <CardPanel>
              <Empty>
                <EmptyHeader>
                  <EmptyMedia variant="icon"><Icon name="folder-plus" size={18} /></EmptyMedia>
                  <EmptyTitle>No projects in {WORKSPACE.name}</EmptyTitle>
                  <EmptyDescription>
                    Without one, every chat starts from nothing. A project carries instructions and files into every thread opened inside it — the {data.files.filter(FILE_FLAGS.inContext).length} indexed files in the workspace can be moved into one.
                  </EmptyDescription>
                </EmptyHeader>
                <EmptyContent><Button onClick={onNew}>New project</Button></EmptyContent>
              </Empty>
            </CardPanel>
          </Card>
        </div>
      );
    }
    return (
      <div className="pl-page">
        <PageHead
          title="Projects"
          note="A project holds its own instructions and its own files, and every thread inside it is sent both."
          actions={<Button size="sm" onClick={onNew}><Icon name="plus" size={14} />New project</Button>}
        />
        <FilterBar query={query} onQuery={setQuery} placeholder="Search projects" dirty={dirty} onClear={clear}
          selects={[{ id: "shelf", label: "Shelf", value: shelf, onChange: setShelf, items: [
            { value: "live", label: "Live" }, { value: "archived", label: "Archived" }, { value: "all", label: "All projects" },
          ] }]} />
        {matched.length ? (
          <>
            <div className="pl-columns pl-columns--even" style={{ gridTemplateColumns: "minmax(0,1fr) minmax(0,1fr)" }}>
              {intoColumns(matched, 2).map((column, i) => (
                <div className="pl-col" key={i}>
                  {column.map((project) => <ProjectCard key={project.id} project={project} data={data} onNavigate={onNavigate} onRun={onRun} />)}
                </div>
              ))}
            </div>
            <p className="pl-foot">
              Showing {matched.length} of {data.projects.length} projects · {threadsInProjects(data.threads, matched)} threads inside them
            </p>
          </>
        ) : (
          <Card><NoResults title="No project matches that" description={"Nothing on the " + shelf + " shelf matches \u201c" + query.trim() + "\u201d."} onClear={clear} /></Card>
        )}
      </div>
    );
  }

  const threadsInProjects = (threads, projects) => threads.filter((t) => projects.some((p) => p.id === t.projectId)).length;

  function ProjectScreen({ project, data, onNavigate, onRun, onRunFile, onNewThread }) {
    const threads = threadsInProject(data.threads, project.id);
    const files = filesInProject(data.files, project.id);
    const stuck = files.filter(FILE_FLAGS.needsAttention);
    const rows = billingRows(threads, data.files);
    const owner = personById(data.people, project.ownerId);
    const archived = PROJECT_FLAGS.isArchived(project);
    return (
      <div className="pl-page">
        <PageHead
          title={project.name}
          note={project.purpose}
          actions={
            <span className="pl-chips">
              {archived ? <Badge size="sm" variant="secondary">Archived</Badge> : <VisibilityBadge value={project.visibility} />}
              {archived ? null : <Button size="sm" onClick={() => onNewThread(project)}><Icon name="pen-line" size={14} />New chat</Button>}
              <RowActions transitions={projectTransitions(project)} onRun={(t) => onRun(project, t)} label={"Actions for " + project.name} />
            </span>
          }
        />
        <AnchorRow items={[
          { label: "Threads", value: String(threads.length), qualifier: threads.length ? "Last reply " + formatAge(Math.max.apply(null, threads.map((t) => THREAD_FLAGS.lastActivityAt(t))), data.now) : "None yet" },
          { label: "Billed turns", value: String(rows.length), qualifier: "Across every thread in this project" },
          { label: "Tokens", value: formatTokens(tokensOf(rows)), qualifier: "Read and written, this project only" },
          { label: "Cost", value: formatCost(costOf(rows)), qualifier: "At the rates on the models page" },
        ]} />
        <div className="pl-columns">
          <div className="pl-col">
            <Card className="pl-card-full">
              <CardHeader>
                <CardTitle>Threads</CardTitle>
                <CardDescription>Every conversation started inside this project.</CardDescription>
              </CardHeader>
              <CardPanel className="pl-card-table">
                {threads.length ? (
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>Thread</TableHead>
                        <TableHead className="pl-drop-md">Model</TableHead>
                        <TableHead className="pl-num">Turns</TableHead>
                        <TableHead className="pl-num">Cost</TableHead>
                        <TableHead>Last reply</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {threads.map((thread) => {
                        const billing = threadBilling(thread, data.files);
                        return (
                          <TableRow key={thread.id}>
                            <TableCell>
                              <span className="pl-record">
                                <button type="button" className="pl-record__name pl-link" onClick={() => onNavigate(resolvePath("/chats/:id", { id: thread.id }))}>{thread.title}</button>
                                <span className="pl-record__meta">{personById(data.people, thread.ownerId).name} · {statusValue(VISIBILITY, thread.visibility).label.toLowerCase()}</span>
                              </span>
                            </TableCell>
                            <TableCell className="pl-drop-md">{labelOf(MODELS, thread.model)}</TableCell>
                            <TableCell className="pl-num">{billing.rows.length}</TableCell>
                            <TableCell className="pl-num">{formatCost(billing.cost)}</TableCell>
                            <TableCell title={formatAbsolute(THREAD_FLAGS.lastActivityAt(thread))}><span className="pl-when">{formatWhen(THREAD_FLAGS.lastActivityAt(thread), data.now)}</span></TableCell>
                          </TableRow>
                        );
                      })}
                    </TableBody>
                  </Table>
                ) : (
                  <Empty>
                    <EmptyHeader>
                      <EmptyMedia variant="icon"><Icon name="message-square-plus" size={18} /></EmptyMedia>
                      <EmptyTitle>No threads in {project.name} yet</EmptyTitle>
                      <EmptyDescription>A thread started here is sent the instructions and the {files.length} files below.</EmptyDescription>
                    </EmptyHeader>
                    <EmptyContent><Button onClick={() => onNewThread(project)}>New chat</Button></EmptyContent>
                  </Empty>
                )}
              </CardPanel>
            </Card>
          </div>
          <div className="pl-col">
            <Card className="pl-card-full">
              <CardHeader>
                <CardTitle>Instructions</CardTitle>
                <CardDescription>Sent ahead of every turn in this project.</CardDescription>
              </CardHeader>
              <CardPanel>
                <p className="pl-instructions">{project.instructions}</p>
              </CardPanel>
              <CardFooter><span className="pl-foot">Owned by {owner.name} · started {formatDay(project.createdAt)}</span></CardFooter>
            </Card>
            <Card className="pl-card-full">
              <CardHeader>
                <CardTitle>Files</CardTitle>
                <CardDescription>
                  {stuck.length
                    ? stuck.length + " of " + files.length + " could not be read, so nothing in " + (stuck.length === 1 ? "it" : "them") + " reaches a thread."
                    : "All " + files.length + " are indexed and readable."}
                </CardDescription>
              </CardHeader>
              <CardPanel>
                <div className="pl-stack--tight" style={{ display: "flex", flexDirection: "column" }}>
                  {files.map((file) => (
                    <div className="pl-setting" key={file.id}>
                      <span className="pl-setting__text">
                        <FileLine file={file} showStatus />
                      </span>
                      <span className="pl-chips">
                        <StatusBadge values={FILE_STATUS} value={file.status} />
                        <RowActions transitions={fileTransitions(file)} onRun={(t) => onRunFile(file, t)} label={"Actions for " + file.name} />
                      </span>
                    </div>
                  ))}
                </div>
              </CardPanel>
            </Card>
          </div>
        </div>
      </div>
    );
  }

  /* ── Library ───────────────────────────────────────────────────────── */

  function LibraryScreen({ data, user, onNavigate, onRun, onNew }) {
    const [query, setQuery] = React.useState("");
    const [category, setCategory] = React.useState("all");
    const matched = data.prompts.filter((p) => {
      if (category !== "all" && p.category !== category) return false;
      return (p.title + " " + p.body).toLowerCase().indexOf(query.toLowerCase().trim()) > -1;
    }).sort((a, b) => b.uses - a.uses);
    const stale = matched.filter((p) => PROMPT_FLAGS.isStale(p, data.now));
    const dirty = query.trim().length > 0 || category !== "all";
    const clear = () => { setQuery(""); setCategory("all"); };
    if (!data.prompts.length) {
      return (
        <div className="pl-page">
          <PageHead title="Library" note="Prompts anyone here can drop into a composer." />
          <Card>
            <CardPanel>
              <Empty>
                <EmptyHeader>
                  <EmptyMedia variant="icon"><Icon name="bookmark-plus" size={18} /></EmptyMedia>
                  <EmptyTitle>Nothing saved yet</EmptyTitle>
                  <EmptyDescription>A prompt worth typing twice is worth saving once. Saved ones are shared with everyone in {WORKSPACE.name} and the four most used sit in the composer's own menu.</EmptyDescription>
                </EmptyHeader>
                <EmptyContent><Button onClick={onNew}>New prompt</Button></EmptyContent>
              </Empty>
            </CardPanel>
          </Card>
        </div>
      );
    }
    return (
      <div className="pl-page">
        <PageHead
          title="Library"
          note="Prompts anyone here can drop into a composer. The four most used are in the composer's own menu."
          actions={<Button size="sm" onClick={onNew}><Icon name="plus" size={14} />New prompt</Button>}
        />
        <FilterBar query={query} onQuery={setQuery} placeholder="Search prompts" dirty={dirty} onClear={clear}
          selects={[{ id: "cat", label: "Category", value: category, onChange: setCategory, items: [{ value: "all", label: "All categories" }].concat(PROMPT_CATEGORIES) }]} />
        {matched.length ? (
          <Card className="pl-card-full">
            <CardPanel className="pl-card-table">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Prompt</TableHead>
                    <TableHead className="pl-drop-md">Category</TableHead>
                    <TableHead className="pl-num">Uses</TableHead>
                    <TableHead>Last used</TableHead>
                    <TableHead className="pl-actions-head">Actions</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {matched.map((prompt) => {
                    const dusty = PROMPT_FLAGS.isStale(prompt, data.now);
                    return (
                      <TableRow key={prompt.id} className={dusty ? "pl-row--recessed" : undefined}>
                        <TableCell>
                          <span className="pl-record">
                            <button type="button" className="pl-record__name pl-link" onClick={() => onNavigate(resolvePath("/library/:id", { id: prompt.id }))}>{prompt.title}</button>
                            <span className="pl-record__meta">{prompt.body.length > 96 ? prompt.body.slice(0, 96).trim() + "…" : prompt.body}</span>
                          </span>
                        </TableCell>
                        <TableCell className="pl-drop-md">{labelOf(PROMPT_CATEGORIES, prompt.category)}</TableCell>
                        <TableCell className="pl-num">{prompt.uses}</TableCell>
                        <TableCell title={formatAbsolute(prompt.lastUsedAt)}>
                          <span className="pl-when">{formatWhen(prompt.lastUsedAt, data.now)}</span>
                          {dusty ? <span className="pl-sub">Not used in two months</span> : null}
                        </TableCell>
                        <TableCell className="pl-actions">
                          <RowActions transitions={promptTransitions(prompt)} onRun={(t) => onRun(prompt, t)} label={"Actions for " + prompt.title} />
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </CardPanel>
            <CardFooter>
              <span className="pl-foot">
                Showing {matched.length} of {data.prompts.length} prompts
                {stale.length ? " · " + stale.length + " not used in two months, shown recessed" : ""}
              </span>
            </CardFooter>
          </Card>
        ) : (
          <Card><NoResults title="No prompt matches that" description={"Nothing in " + (category === "all" ? "the library" : labelOf(PROMPT_CATEGORIES, category).toLowerCase()) + " matches \u201c" + query.trim() + "\u201d."} onClear={clear} /></Card>
        )}
      </div>
    );
  }

  /* ── Files ─────────────────────────────────────────────────────────── */

  function FilesScreen({ data, onNavigate, onRun, onUpload }) {
    const [query, setQuery] = React.useState("");
    const [status, setStatus] = React.useState("all");
    const stuck = data.files.filter(FILE_FLAGS.needsAttention);
    const matched = data.files.filter((f) => {
      if (status === "attention" && !FILE_FLAGS.needsAttention(f)) return false;
      if (status !== "all" && status !== "attention" && f.status !== status) return false;
      return f.name.toLowerCase().indexOf(query.toLowerCase().trim()) > -1;
    }).sort((a, b) => b.at - a.at);
    const dirty = query.trim().length > 0 || status !== "all";
    const clear = () => { setQuery(""); setStatus("all"); };
    const readable = matched.filter(FILE_FLAGS.inContext);
    if (!data.files.length) {
      return (
        <div className="pl-page">
          <PageHead title="Files" note="Anything uploaded here can be attached to a thread and is then read on every turn."
            actions={<Button size="sm" onClick={onUpload}><Icon name="upload" size={14} />Upload files</Button>} />
          <Card>
            <CardPanel>
              <Empty>
                <EmptyHeader>
                  <EmptyMedia variant="icon"><Icon name="upload" size={18} /></EmptyMedia>
                  <EmptyTitle>Nothing uploaded</EmptyTitle>
                  <EmptyDescription>Text, PDFs and spreadsheets are read; archives and binaries are not. A file costs nothing until it is attached to a thread, and then it is re-read on every turn.</EmptyDescription>
                </EmptyHeader>
                <EmptyContent><Button onClick={onUpload}>Upload files</Button></EmptyContent>
              </Empty>
            </CardPanel>
          </Card>
        </div>
      );
    }
    return (
      <div className="pl-page">
        <PageHead
          title="Files"
          note={stuck.length
            ? stuck.length + " of " + data.files.length + " files could not be read. Nothing in them reaches a thread, and no turn that cites them is telling the whole story."
            : "Every file here is indexed and can be attached to any thread."}
          actions={<Button size="sm" onClick={onUpload}><Icon name="upload" size={14} />Upload files</Button>}
        />
        <FilterBar query={query} onQuery={setQuery} placeholder="Search files" dirty={dirty} onClear={clear}
          selects={[{ id: "status", label: "Status", value: status, onChange: setStatus, items: [
            { value: "all", label: "All files" },
            { value: "attention", label: "Needs you (" + stuck.length + ")" },
          ].concat(FILE_STATUS.map((s) => ({ value: s.id, label: s.label }))) }]} />
        {matched.length ? (
          <Card className="pl-card-full">
            <CardPanel className="pl-card-table">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>File</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead className="pl-drop-md">Project</TableHead>
                    <TableHead className="pl-num">Tokens</TableHead>
                    <TableHead>Uploaded</TableHead>
                    <TableHead className="pl-actions-head">Actions</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {matched.map((file) => {
                    const project = file.projectId ? projectById(data.projects, file.projectId) : null;
                    const out = !FILE_FLAGS.inContext(file);
                    return (
                      <TableRow key={file.id} className={out ? "pl-row--recessed" : undefined}>
                        <TableCell>
                          <span className="pl-record">
                            <button type="button" className="pl-record__name pl-link" onClick={() => onNavigate(resolvePath("/files/:id", { id: file.id }))}>{file.name}</button>
                            <span className="pl-record__meta">{formatBytes(file.bytes)} · {file.note}</span>
                          </span>
                        </TableCell>
                        <TableCell>
                          <span className="pl-record">
                            <StatusBadge values={FILE_STATUS} value={file.status} />
                            {file.statusNote ? <span className="pl-sub">{file.statusNote}</span> : null}
                          </span>
                        </TableCell>
                        <TableCell className="pl-drop-md">
                          {project
                            ? <button type="button" className="pl-link" onClick={() => onNavigate(resolvePath("/projects/:id", { id: project.id }))}>{project.name}</button>
                            : <span className="pl-muted">Workspace</span>}
                        </TableCell>
                        <TableCell className="pl-num">{FILE_FLAGS.inContext(file) ? formatTokens(file.tokens) : <span className="pl-muted">—</span>}</TableCell>
                        <TableCell title={formatAbsolute(file.at)}>
                          <span className="pl-when">{formatWhen(file.at, data.now)}</span>
                          <span className="pl-sub">{personById(data.people, file.uploadedBy).name.split(" ")[0]}</span>
                        </TableCell>
                        <TableCell className="pl-actions">
                          <RowActions transitions={fileTransitions(file)} onRun={(t) => onRun(file, t)} label={"Actions for " + file.name} />
                        </TableCell>
                      </TableRow>
                    );
                  })}
                </TableBody>
              </Table>
            </CardPanel>
            <CardFooter>
              <span className="pl-foot">
                Showing {matched.length} of {data.files.length} files · {readable.length} readable, carrying {formatTokens(readable.reduce((sum, f) => sum + f.tokens, 0))} tokens between them
              </span>
            </CardFooter>
          </Card>
        ) : (
          <Card><NoResults title="No file matches that" description={"Nothing matches \u201c" + query.trim() + "\u201d in that status."} onClear={clear} /></Card>
        )}
      </div>
    );
  }

  Object.assign(window, { ProjectsScreen, ProjectScreen, LibraryScreen, FilesScreen });
})();
