import type { C1ProjectOverviewPayload, C1TaskFixturePayload } from "./model.js";
import { escapeHtml, titleCase } from "./html.js";
import { renderLifecycleShell, renderStateBanner } from "./shell.js";
import { withQuery } from "./router.js";

const taskById = (
  tasks: readonly C1TaskFixturePayload[],
  id: string,
): C1TaskFixturePayload | undefined => tasks.find((task) => task.id === id);
const blocks = (
  task: C1TaskFixturePayload,
  tasks: readonly C1TaskFixturePayload[],
): readonly C1TaskFixturePayload[] =>
  tasks.filter((candidate) => candidate.dependencyIds.includes(task.id));
const dependencyText = (
  task: C1TaskFixturePayload,
  tasks: readonly C1TaskFixturePayload[],
): string =>
  task.dependencyIds.length === 0
    ? "No hard prerequisites"
    : `Depends on ${task.dependencyIds.map((id) => taskById(tasks, id)?.title ?? id).join(", ")}`;

const queueRows = (
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
  selected?: string,
): string => {
  const sections = [
    ["Running", ["RUNNING"]],
    ["Ready / Next", ["READY"]],
    ["Blocked", ["BLOCKED_DEPENDENCY", "BLOCKED_POLICY"]],
    ["Waiting on you", ["WAITING_USER"]],
    ["Paused", ["PAUSED"]],
    ["Recently completed", ["DONE", "CANCELLED"]],
  ] as const;
  return sections
    .map(([title, states]) => {
      const entries = model.queue.filter((entry) => states.includes(entry.readinessState as never));
      const rows =
        entries.length === 0
          ? '<div class="queue-empty">No work in this state.</div>'
          : entries
              .map((entry, index) => {
                const task = taskById(tasks, entry.taskId);
                const dependents = task ? blocks(task, tasks) : [];
                const tone =
                  entry.readinessState === "READY" || entry.readinessState === "DONE"
                    ? "green"
                    : entry.readinessState.startsWith("BLOCKED")
                      ? "red"
                      : "blue";
                return `<article class="queue-row${selected === entry.taskId ? " selected" : ""}" id="task-${entry.taskId}"><a class="queue-row-main" href="${withQuery(`/projects/${model.project.id}/queue`, { view: "queue", task: entry.taskId })}"${selected === entry.taskId ? ' aria-current="true"' : ""}><span class="queue-position">${entry.position + 1}</span><span><strong>${escapeHtml(task?.title ?? entry.taskId)}</strong><small>Plan revision ${escapeHtml(entry.planRevisionId)} · ${task ? escapeHtml(dependencyText(task, tasks)) : "Dependency detail unavailable"}</small></span><span class="pill ${tone}">${titleCase(entry.readinessState)}</span></a><div class="dependency-affordances">${task?.dependencyIds.length ? `<span>Depends on ${task.dependencyIds.length}</span>` : ""}${dependents.length ? `<span>Blocks ${dependents.length}</span>` : ""}${index === 0 && title === "Ready / Next" ? '<strong class="next-dispatch">Next dispatch candidate</strong>' : ""}</div></article>`;
              })
              .join("");
      return `<section class="panel queue-section"><div class="panel-head"><h2>${title}</h2><p>${entries.length} item${entries.length === 1 ? "" : "s"}</p></div><div class="queue-list">${rows}</div></section>`;
    })
    .join("");
};

const graphView = (
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
  selected?: string,
): string => {
  const selectedTask = selected ? taskById(tasks, selected) : undefined;
  const nodes = tasks
    .map((task, index) => {
      const related = selectedTask
        ? selectedTask.id === task.id ||
          selectedTask.dependencyIds.includes(task.id) ||
          task.dependencyIds.includes(selectedTask.id)
        : true;
      return `<a class="graph-node${task.id === selected ? " selected" : ""}${related ? "" : " dimmed"}" href="${withQuery(`/projects/${model.project.id}/queue`, { view: "graph", task: task.id })}" data-task-node="${task.id}"><span class="node-index">${index + 1}</span><strong>${escapeHtml(task.title)}</strong><small>${titleCase(task.status)}</small><span>${task.dependencyIds.length ? `${task.dependencyIds.length} prerequisite` : "No prerequisites"}</span></a>`;
    })
    .join('<span class="graph-arrow" aria-hidden="true">→</span>');
  const relationships = tasks
    .map(
      (task) =>
        `<div class="relationship-row"><strong>${escapeHtml(task.title)}</strong><span>${escapeHtml(dependencyText(task, tasks))}</span><span>${
          blocks(task, tasks).length
            ? `Blocks ${blocks(task, tasks)
                .map((dependent) => escapeHtml(dependent.title))
                .join(", ")}`
            : "Blocks no Task"
        }</span></div>`,
    )
    .join("");
  return `<section class="panel graph-panel"><div class="panel-head"><h2>Dependency Graph</h2><p>Prerequisite → dependent. Graph and accessible relationship list are one projection of the same authoritative Task projection.</p></div><div class="graph-toolbar" aria-label="Graph controls"><label>Focus Task<select data-graph-select><option value="">All Tasks</option>${tasks.map((task) => `<option value="${task.id}"${task.id === selected ? " selected" : ""}>${escapeHtml(task.title)}</option>`).join("")}</select></label><a class="btn" href="/projects/${model.project.id}/queue?view=graph">Reset view</a></div><div class="compound-graph" role="img" aria-label="Task dependency graph"><div class="plan-group"><div class="plan-group-head"><strong>${escapeHtml(model.plans[0]?.title ?? "I1 Plan")}</strong><span>${tasks.length} Tasks · ${tasks.filter((task) => task.status === "completed").length} completed</span></div><div class="graph-nodes">${nodes}</div></div></div><div class="relationship-list"><h3>Accessible dependency relationships</h3>${relationships}</div></section>`;
};

export function renderQueuePage(
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
  view: string,
  state: string,
  selected?: string,
): string {
  const activeView = view === "graph" ? "graph" : "queue";
  const selectedSummary = selected
    ? (() => {
        const task = taskById(tasks, selected);
        if (!task) return "<p>Unknown Task.</p>";
        const downstream = blocks(task, tasks);
        return `<div class="callout purple"><div class="callout-title">${escapeHtml(task.title)}</div><div class="callout-sub">${escapeHtml(dependencyText(task, tasks))}</div></div><div class="detail-row"><b>Blocks</b><span>${downstream.length ? downstream.map((item) => escapeHtml(item.title)).join(", ") : "None"}</span></div><div class="detail-row"><b>Preview rule</b><span>UI movement feedback is advisory; only the application command decides whether a reorder is accepted.</span></div><div class="mini-actions"><button class="btn" type="button" data-command="move-up" data-task="${task.id}">Move up</button><button class="btn" type="button" data-command="move-down" data-task="${task.id}">Move down</button></div>`;
      })()
    : '<p class="subtle">Select a Task to inspect prerequisites, dependents, and keyboard move previews.</p>';
  const body =
    activeView === "queue"
      ? `<div class="queue-page-layout"><div>${queueRows(model, tasks, selected)}</div><aside class="panel dependency-summary"><div class="panel-head"><h2>Selected dependency context</h2><p>Text equivalent for movement constraints.</p></div><div class="panel-body">${selectedSummary}</div></aside></div>`
      : graphView(model, tasks, selected);
  const content = `${renderStateBanner(state, "project")}<div class="run-head queue-page-head"><div><div class="run-title">Queue / Dependency Graph</div><div class="context-strip"><span class="pill green">Project ${escapeHtml(model.project.name)}</span><span>Server/application legality remains authoritative</span><span class="divider"></span><span>Client movement feedback is preview only</span></div></div></div><nav class="tabs queue-tabs" aria-label="Queue views"><a class="tab${activeView === "queue" ? " active" : ""}" href="${withQuery(`/projects/${model.project.id}/queue`, { view: "queue", task: selected })}"${activeView === "queue" ? ' aria-current="page"' : ""}>Queue</a><a class="tab${activeView === "graph" ? " active" : ""}" href="${withQuery(`/projects/${model.project.id}/queue`, { view: "graph", task: selected })}"${activeView === "graph" ? ' aria-current="page"' : ""}>Graph</a></nav>${body}`;
  return renderLifecycleShell({
    active: "queues",
    breadcrumbs: ["AWP", model.project.name, "Queues"],
    content,
    project: { id: model.project.id, name: model.project.name },
    ...(model.factoryRuns.at(-1)?.id === undefined
      ? {}
      : { latestFactoryRunId: model.factoryRuns.at(-1)!.id }),
  });
}
