import React from "react";
import { fmtClock, fmtDate } from "./time";
import { LoadingTitle } from "./loading-indicator";
import { errorMessage, requestJson } from "./unidesk-error";
import { UniDeskErrorBanner } from "./unidesk-error-banner";

type AnyRecord = Record<string, any>;

const h = React.createElement;
const { useEffect, useMemo } = React;
const useState: any = React.useState;

function StatusBadge({ status, children }: AnyRecord) {
  const normalized = String(status || "unknown").toLowerCase();
  return h("span", { className: `status-badge ${normalized}` }, children || status || "unknown");
}

function MetricCard({ label, value, hint, tone }: AnyRecord) {
  return h("article", { className: `metric-card ${tone || ""}` },
    h("div", { className: "metric-label" }, label),
    h("div", { className: "metric-value" }, value),
    h("div", { className: "metric-hint" }, hint),
  );
}

function Panel({ title, eyebrow, actions, children, className, loading }: AnyRecord) {
  return h("section", { className: `panel ${className || ""}` },
    h("div", { className: "panel-head" },
      h("div", null,
        eyebrow ? h("p", { className: "panel-eyebrow" }, eyebrow) : null,
        h(LoadingTitle, { title, loading }),
      ),
      actions ? h("div", { className: "panel-actions" }, actions) : null,
    ),
    h("div", { className: "panel-body" }, children),
  );
}

function RawButton({ title, data, onOpen, testId }: AnyRecord) {
  return h("button", {
    type: "button",
    className: "ghost-btn",
    "data-testid": testId,
    onClick: () => onOpen(title, data),
  }, "查看原始JSON");
}

function EmptyState({ title, text }: AnyRecord) {
  return h("div", { className: "empty-state" }, h("strong", null, title), h("span", null, text));
}

function microserviceRuntime(service: any): AnyRecord {
  return service?.runtime && typeof service.runtime === "object" && !Array.isArray(service.runtime) ? service.runtime : {};
}

function microserviceBackend(service: any): AnyRecord {
  return service?.backend && typeof service.backend === "object" && !Array.isArray(service.backend) ? service.backend : {};
}

function microserviceRepository(service: any): AnyRecord {
  return service?.repository && typeof service.repository === "object" && !Array.isArray(service.repository) ? service.repository : {};
}

function mdtodoApi(apiBaseUrl: string, path: string): string {
  return `${apiBaseUrl}/microservices/mdtodo/proxy${path}`;
}

function statusLabel(status: string): string {
  if (status === "completed") return "已完成";
  if (status === "in_progress") return "进行中";
  return "待处理";
}

function statusTone(status: string): string {
  if (status === "completed") return "online";
  if (status === "in_progress") return "warn";
  return "unknown";
}

function flattenTasks(tasks: any[]): any[] {
  const rows: any[] = [];
  const visit = (items: any[]) => {
    for (const task of items) {
      rows.push(task);
      if (Array.isArray(task.children)) visit(task.children);
    }
  };
  visit(Array.isArray(tasks) ? tasks : []);
  return rows;
}

function TaskTree({ tasks, selectedId, onSelect }: AnyRecord) {
  if (!tasks.length) return h(EmptyState, { title: "暂无任务", text: "当前文件没有 R 编号任务。" });
  const renderTask = (task: AnyRecord): React.ReactElement => h("li", { key: task.id },
    h("button", {
      type: "button",
      className: `mdtodo-task-row ${selectedId === task.id ? "active" : ""}`,
      style: { "--task-depth": Math.min(Number(task.depth || 0), 6) },
      onClick: () => onSelect(task.id),
      "data-testid": `mdtodo-task-${String(task.id).replace(/[^A-Za-z0-9_-]+/g, "-")}`,
    },
      h(StatusBadge, { status: statusTone(task.status) }, statusLabel(task.status)),
      h("code", null, task.id),
      h("span", { className: "mdtodo-task-title" }, task.title || "--"),
      h("span", { className: "mdtodo-link-count" }, `${task.linkExists ?? 0}/${task.linkCount ?? 0}`),
    ),
    Array.isArray(task.children) && task.children.length > 0 ? h("ol", null, task.children.map(renderTask)) : null,
  );
  return h("ol", { className: "mdtodo-tree" }, tasks.map(renderTask));
}

export function MdtodoPage({ microservices, onRaw, apiBaseUrl = "/api" }: AnyRecord) {
  const service = microservices.find((item: any) => item.id === "mdtodo") || null;
  const [state, setState] = useState({ loading: false, saving: false, error: "", notice: "", health: null, files: [], todo: null, selectedFile: "", selectedTaskId: "", refreshedAt: null, command: null });
  const [draftTitle, setDraftTitle] = useState("");
  const [draftRaw, setDraftRaw] = useState("");
  const [newTaskTitle, setNewTaskTitle] = useState("");

  const tasks = Array.isArray(state.todo?.tasks) ? state.todo.tasks : [];
  const flatTasks = useMemo(() => flattenTasks(tasks), [state.todo]);
  const selectedTask = flatTasks.find((task: any) => task.id === state.selectedTaskId) || flatTasks[0] || null;
  const stats = state.todo?.stats || {};

  async function load(filePath = state.selectedFile): Promise<void> {
    if (!service) return;
    setState((prev: any) => ({ ...prev, loading: true, error: "", notice: "" }));
    try {
      const [health, fileList] = await Promise.all([
        requestJson(`${apiBaseUrl}/microservices/mdtodo/health`),
        requestJson(mdtodoApi(apiBaseUrl, "/api/files")),
      ]);
      const files = Array.isArray(fileList.files) ? fileList.files : [];
      const selectedFile = filePath || files[0]?.path || "";
      const todo = selectedFile ? await requestJson(mdtodoApi(apiBaseUrl, `/api/tasks?file=${encodeURIComponent(selectedFile)}`)) : null;
      const nextTasks = Array.isArray(todo?.tasks) ? flattenTasks(todo.tasks) : [];
      const nextSelectedTaskId = nextTasks.some((task: any) => task.id === state.selectedTaskId)
        ? state.selectedTaskId
        : nextTasks[0]?.id || "";
      setState({ loading: false, saving: false, error: "", notice: "", health, files, todo, selectedFile, selectedTaskId: nextSelectedTaskId, refreshedAt: new Date(), command: state.command });
    } catch (err) {
      setState((prev: any) => ({ ...prev, loading: false, error: errorMessage(err, "MDTODO 加载失败") }));
    }
  }

  useEffect(() => {
    load();
  }, [service?.id, service?.runtime?.providerStatus]);

  useEffect(() => {
    setDraftTitle(selectedTask?.title || "");
    setDraftRaw(selectedTask?.rawContent || "");
  }, [selectedTask?.id, state.selectedFile]);

  if (!service) return h(EmptyState, { title: "MDTODO 未登记", text: "请在 config.json 的 microservices 中登记用户服务 id=mdtodo" });

  const runtime = microserviceRuntime(service);
  const repository = microserviceRepository(service);
  const backend = microserviceBackend(service);

  async function selectFile(path: string): Promise<void> {
    setState((prev: any) => ({ ...prev, selectedFile: path, selectedTaskId: "", command: null }));
    await load(path);
  }

  async function patchSelected(patch: AnyRecord): Promise<void> {
    if (!selectedTask || !state.selectedFile) return;
    setState((prev: any) => ({ ...prev, saving: true, error: "", notice: "" }));
    try {
      const result = await requestJson(mdtodoApi(apiBaseUrl, `/api/tasks/${encodeURIComponent(selectedTask.id)}`), {
        method: "PATCH",
        body: { file: state.selectedFile, ...patch },
      });
      setState((prev: any) => ({ ...prev, saving: false, todo: result.file, notice: result.result?.message || "任务已更新" }));
    } catch (err) {
      setState((prev: any) => ({ ...prev, saving: false, error: errorMessage(err, "任务更新失败") }));
    }
  }

  async function saveSelected(): Promise<void> {
    await patchSelected({ title: draftTitle, rawContent: draftRaw });
  }

  async function addTask(parentId?: string): Promise<void> {
    if (!state.selectedFile) return;
    setState((prev: any) => ({ ...prev, saving: true, error: "", notice: "" }));
    try {
      const result = await requestJson(mdtodoApi(apiBaseUrl, "/api/tasks"), {
        method: "POST",
        body: { file: state.selectedFile, parentId, title: newTaskTitle || "新任务" },
      });
      setNewTaskTitle("");
      setState((prev: any) => ({ ...prev, saving: false, todo: result.file, selectedTaskId: result.result?.taskId || prev.selectedTaskId, notice: result.result?.message || "任务已创建" }));
      await load(state.selectedFile);
    } catch (err) {
      setState((prev: any) => ({ ...prev, saving: false, error: errorMessage(err, "创建任务失败") }));
    }
  }

  async function deleteSelected(): Promise<void> {
    if (!selectedTask || !state.selectedFile) return;
    if (!window.confirm(`删除 ${selectedTask.id} 及其子任务?`)) return;
    setState((prev: any) => ({ ...prev, saving: true, error: "", notice: "" }));
    try {
      const result = await requestJson(mdtodoApi(apiBaseUrl, `/api/tasks/${encodeURIComponent(selectedTask.id)}?file=${encodeURIComponent(state.selectedFile)}`), { method: "DELETE" });
      const nextTasks = flattenTasks(result.file?.tasks || []);
      setState((prev: any) => ({ ...prev, saving: false, todo: result.file, selectedTaskId: nextTasks[0]?.id || "", notice: result.result?.message || "任务已删除" }));
    } catch (err) {
      setState((prev: any) => ({ ...prev, saving: false, error: errorMessage(err, "删除任务失败") }));
    }
  }

  async function generateCommand(): Promise<void> {
    if (!selectedTask || !state.selectedFile) return;
    setState((prev: any) => ({ ...prev, saving: true, error: "", command: null }));
    try {
      const command = await requestJson(mdtodoApi(apiBaseUrl, "/api/execute-command"), {
        method: "POST",
        body: { file: state.selectedFile, taskId: selectedTask.id, mode: "codex" },
      });
      setState((prev: any) => ({ ...prev, saving: false, command, notice: "执行命令已生成" }));
    } catch (err) {
      setState((prev: any) => ({ ...prev, saving: false, error: errorMessage(err, "执行命令生成失败") }));
    }
  }

  return h("div", { className: "mdtodo-page", "data-testid": "mdtodo-page" },
    h(Panel, {
      title: "MDTODO 工作台",
      eyebrow: "D601 k3s managed service",
      loading: state.loading,
      actions: h("div", { className: "panel-actions" },
        h("button", { type: "button", className: "ghost-btn", onClick: () => void load(), disabled: state.loading, "data-testid": "mdtodo-refresh-button" }, state.loading ? "刷新中" : "刷新"),
        h(RawButton, { title: "MDTODO 用户服务", data: service, onOpen: onRaw, testId: "raw-mdtodo-service" }),
      ),
    },
      h("div", { className: "findjob-hero" },
        h("div", null,
          h("div", { className: "node-version-line" },
            h(StatusBadge, { status: runtime.providerStatus === "online" ? "online" : "warn" }, runtime.providerStatus || "unknown"),
            h("span", null, service.providerId),
            h("span", null, backend.proxyMode || "--"),
          ),
          h("p", { className: "muted paragraph" }, service.description),
        ),
        h("div", { className: "microservice-ref-card" },
          h("span", null, "Repo"),
          h("strong", null, repository.url || "--"),
          h("code", null, repository.composeFile || "--"),
        ),
        h("div", { className: "microservice-ref-card" },
          h("span", null, "Workspace"),
          h("strong", null, state.health?.rootDir || "/workspace"),
          h("code", null, `${backend.nodeBindHost || "--"}:${backend.nodePort || "--"}`),
        ),
      ),
      h(UniDeskErrorBanner, { error: state.error, wide: true }),
      state.notice ? h("div", { className: "notice-line" }, state.notice) : null,
    ),
    h("div", { className: "metric-grid" },
      h(MetricCard, { label: "TODO 文件", value: state.files.length, hint: state.health?.rootExists ? "hostPath ready" : "hostPath missing", tone: state.health?.ok ? "ok" : "warn" }),
      h(MetricCard, { label: "任务总数", value: stats.total ?? "--", hint: state.selectedFile || "--" }),
      h(MetricCard, { label: "已完成", value: stats.completed ?? "--", hint: "completed", tone: "ok" }),
      h(MetricCard, { label: "进行中", value: stats.inProgress ?? "--", hint: "in progress", tone: "warn" }),
      h(MetricCard, { label: "待处理", value: stats.pending ?? "--", hint: state.refreshedAt ? fmtClock(state.refreshedAt) : "pending" }),
    ),
    h("div", { className: "mdtodo-layout" },
      h(Panel, { title: "文件", eyebrow: `${state.files.length} Markdown`, loading: state.loading, className: "mdtodo-file-panel" },
        state.files.length === 0 ? h(EmptyState, { title: "暂无 TODO 文件", text: "等待后端扫描 MDTODO 工作区。" }) :
          h("div", { className: "mdtodo-file-list" }, state.files.map((file: any) => h("button", {
            key: file.path,
            type: "button",
            className: `mdtodo-file-item ${state.selectedFile === file.path ? "active" : ""}`,
            onClick: () => void selectFile(file.path),
          },
            h("strong", null, file.name),
            h("span", null, file.directory || "."),
            h("code", null, `${file.stats?.total ?? "--"} tasks / ${fmtDate(file.mtime)}`),
          ))),
      ),
      h(Panel, {
        title: "任务树",
        eyebrow: state.selectedFile || "Tasks",
        loading: state.loading,
        actions: h("div", { className: "panel-actions" },
          h("input", { value: newTaskTitle, onChange: (event: any) => setNewTaskTitle(event.target.value), placeholder: "新任务标题", "data-testid": "mdtodo-new-title" }),
          h("button", { type: "button", className: "ghost-btn", onClick: () => void addTask(), disabled: state.saving || !state.selectedFile }, "新增"),
          selectedTask ? h("button", { type: "button", className: "ghost-btn", onClick: () => void addTask(selectedTask.id), disabled: state.saving }, "新增子任务") : null,
          state.todo ? h(RawButton, { title: "MDTODO 当前文件", data: state.todo, onOpen: onRaw, testId: "raw-mdtodo-file" }) : null,
        ),
      },
        h(TaskTree, { tasks, selectedId: selectedTask?.id || "", onSelect: (id: string) => setState((prev: any) => ({ ...prev, selectedTaskId: id, command: null })) }),
      ),
      h(Panel, {
        title: selectedTask ? `${selectedTask.id} 详情` : "任务详情",
        eyebrow: selectedTask ? statusLabel(selectedTask.status) : "Detail",
        loading: state.saving,
        className: "mdtodo-detail-panel",
        actions: selectedTask ? h("div", { className: "panel-actions" },
          h("button", { type: "button", className: "ghost-btn", onClick: () => void patchSelected({ status: "pending" }), disabled: state.saving }, "待处理"),
          h("button", { type: "button", className: "ghost-btn", onClick: () => void patchSelected({ status: "in_progress" }), disabled: state.saving }, "进行中"),
          h("button", { type: "button", className: "primary-btn", onClick: () => void patchSelected({ status: "completed" }), disabled: state.saving }, "完成"),
        ) : null,
      },
        !selectedTask ? h(EmptyState, { title: "未选中任务", text: "请选择一个任务。" }) :
          h("div", { className: "mdtodo-editor" },
            h("label", null, "标题", h("input", { value: draftTitle, onChange: (event: any) => setDraftTitle(event.target.value), "data-testid": "mdtodo-title-input" })),
            h("label", null, "正文", h("textarea", { value: draftRaw, onChange: (event: any) => setDraftRaw(event.target.value), rows: 12, "data-testid": "mdtodo-raw-input" })),
            h("div", { className: "docker-meta compact" },
              h("span", null, `line ${Number(selectedTask.lineNumber ?? 0) + 1}`),
              h("span", null, `depth ${selectedTask.depth ?? 0}`),
              h("span", null, `links ${selectedTask.linkExists ?? 0}/${selectedTask.linkCount ?? 0}`),
            ),
            h("div", { className: "inline-actions" },
              h("button", { type: "button", className: "primary-btn", onClick: saveSelected, disabled: state.saving }, state.saving ? "保存中" : "保存"),
              h("button", { type: "button", className: "ghost-btn", onClick: generateCommand, disabled: state.saving }, "生成执行命令"),
              h("button", { type: "button", className: "danger-btn", onClick: deleteSelected, disabled: state.saving }, "删除"),
              h(RawButton, { title: `MDTODO ${selectedTask.id}`, data: selectedTask, onOpen: onRaw, testId: "raw-mdtodo-task" }),
            ),
            state.command ? h("div", { className: "mdtodo-command" },
              h("span", null, state.command.prompt || "--"),
              h("code", null, state.command.command || "--"),
            ) : null,
          ),
      ),
    ),
  );
}
