import type { HwpodOperationResponse } from "@/types";

export type WorkspacePreviewMode = "text" | "markdown";

export interface BuildOperationPresentation {
  status: string;
  label: string;
  tone: "idle" | "running" | "ok" | "warn" | "error";
  operationId: string | null;
  exitCode: number | null;
  jobId: string | null;
  log: string;
  message: string;
  warningCount: number | null;
  errorCount: number | null;
  elapsedMs: number | null;
  artifacts: Array<{ kind: string; path: string }>;
  terminal: boolean;
}

export function workspacePreviewMode(path: string): WorkspacePreviewMode {
  return /\.(?:md|markdown)$/iu.test(path.trim()) ? "markdown" : "text";
}

export function presentBuildOperation(operation: HwpodOperationResponse | null, pending = false): BuildOperationPresentation {
  if (!operation) {
    return {
      status: pending ? "submitting" : "idle",
      label: pending ? "正在提交编译" : "尚未编译",
      tone: pending ? "running" : "idle",
      operationId: null,
      exitCode: null,
      jobId: null,
      log: "",
      message: "",
      warningCount: null,
      errorCount: null,
      elapsedMs: null,
      artifacts: [],
      terminal: false,
    };
  }

  const activity = record(operation.result);
  const response = record(activity.response);
  const result = Array.isArray(response.results) ? record(response.results[0]) : {};
  const output = record(result.output);
  const commands = Array.isArray(output.commands) ? output.commands.map(record) : [];
  const lastCommand = commands.at(-1) ?? {};
  const stdout = stringValue(output.stdout) || stringValue(lastCommand.stdout);
  const stderr = stringValue(output.stderr) || stringValue(lastCommand.stderr);
  const parsed = parseLastJsonRecord(stdout);
  const parsedResult = record(parsed.result);
  const toolStatus = stringValue(parsed.status).toLowerCase();
  const operationStatus = stringValue(operation.status).toLowerCase() || "unknown";
  const exitCode = numberValue(output.exitCode, lastCommand.exitCode, parsed.return_code, parsed.returnCode);
  const jobId = stringValue(parsed.job_id) || stringValue(parsed.jobId) || null;
  const message = stringValue(parsed.message) || stringValue(parsedResult.message);
  const warningCount = numberValue(parsed.warning_count, parsed.warningCount, parsedResult.warning_count, parsedResult.warningCount);
  const errorCount = numberValue(parsed.error_count, parsed.errorCount, parsed.errors, parsedResult.error_count, parsedResult.errorCount, parsedResult.errors);
  const elapsedMs = numberValue(parsed.elapsed_ms, parsed.elapsedMs, parsedResult.elapsed_ms, parsedResult.elapsedMs);
  const artifacts = [
    ["HEX", parsedResult.hex_file ?? parsedResult.hexFile ?? parsed.hex_file ?? parsed.hexFile],
    ["AXF", parsedResult.axf_file ?? parsedResult.axfFile ?? parsed.axf_file ?? parsed.axfFile],
    ["构建日志", parsedResult._log_file ?? parsedResult.log_file ?? parsedResult.logFile ?? parsedResult.build_log ?? parsedResult.buildLog ?? parsed._log_file ?? parsed.log_file ?? parsed.logFile ?? parsed.build_log ?? parsed.buildLog],
  ].flatMap(([kind, path]) => typeof path === "string" && path.trim() ? [{ kind: String(kind), path: path.trim() }] : []);
  const asyncQueued = parsed.accepted === true && ["queued", "running", "accepted"].includes(toolStatus);
  const failed = operation.error != null
    || activity.ok === false
    || response.ok === false
    || result.ok === false
    || output.ok === false
    || (exitCode !== null && exitCode !== 0)
    || ["failed", "error", "canceled", "cancelled", "timed-out", "timeout"].includes(toolStatus)
    || ["failed", "canceled", "cancelled", "terminated", "timed-out", "timeout"].includes(operationStatus);
  const terminal = !asyncQueued && ["completed", "succeeded", "failed", "canceled", "cancelled", "terminated", "timed-out", "timeout"].includes(operationStatus);
  const running = pending || asyncQueued || ["accepted", "queued", "running", "pending", "in-progress"].includes(operationStatus);
  const log = [stderr ? `stderr\n${stderr.trim()}` : "", stdout ? `stdout\n${stdout.trim()}` : ""].filter(Boolean).join("\n\n");

  const detail = { operationId: operation.operationId, exitCode, jobId, log, message, warningCount, errorCount, elapsedMs, artifacts };
  if (failed) return { status: toolStatus || operationStatus, label: "编译失败", tone: "error", ...detail, terminal: true };
  if (asyncQueued) return { status: toolStatus, label: "构建已排队，等待真实终态", tone: "warn", ...detail, terminal: false };
  if (running) return { status: operationStatus, label: "正在等待 Windows Keil 构建终态", tone: "running", ...detail, terminal: false };
  if (terminal) return { status: operationStatus, label: "编译通过", tone: "ok", ...detail, terminal: true };
  return { status: operationStatus, label: "编译状态未知", tone: "warn", ...detail, terminal: false };
}

function record(value: unknown): Record<string, unknown> {
  return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : {};
}

function stringValue(value: unknown): string {
  return typeof value === "string" ? value.trim() : "";
}

function numberValue(...values: unknown[]): number | null {
  for (const value of values) {
    const number = Number(value);
    if (Number.isFinite(number)) return number;
  }
  return null;
}

function parseLastJsonRecord(value: string): Record<string, unknown> {
  if (!value) return {};
  try { return record(JSON.parse(value)); }
  catch {
    let start = value.lastIndexOf("{");
    while (start >= 0) {
      try { return record(JSON.parse(value.slice(start).trim())); }
      catch { start = value.lastIndexOf("{", start - 1); }
    }
    return {};
  }
}
