/**
 * 制御盤のログモーダルの表示用文言・整形（指示書BJ 段階4。表E）。
 * ★純粋関数★。`DeviceLogsModal` から移した。
 */
import { ApiFetchError } from "@/lib/api/client";
import { EXPORT_MAX_BYTES } from "@/lib/config/ds-agent";
import { EXPORT_FILE_IDS_TOO_LARGE_MESSAGE } from "@/lib/ds-logs/validate";
import { formatHm, formatMd } from "@/lib/format/date";
import type { ApiErrorDetails } from "@/lib/types";

export function formatDateTime(iso: string): string {
  return `${formatMd(iso)} ${formatHm(iso)}`;
}

/** 大きさの表示（一覧・選択合計・上限の文言）。1MB 未満は KB、以上は MB */
export function formatFileSize(bytes: number): string {
  if (bytes >= 1024 * 1024) {
    const mb = bytes / (1024 * 1024);
    const text = Number.isInteger(mb) ? String(mb) : mb.toFixed(1);
    return `${text} MB`;
  }
  return `${Math.round(bytes / 1024)} KB`;
}

export function detailStrings(details: ApiErrorDetails, key: string): string[] {
  if (details === null || typeof details !== "object") return [];
  const value = (details as Record<string, unknown>)[key];
  if (!Array.isArray(value)) return [];
  return value.filter((v): v is string => typeof v === "string");
}

function isAbortCause(cause: unknown): boolean {
  return (
    cause !== null &&
    typeof cause === "object" &&
    "name" in cause &&
    (cause as { name: unknown }).name === "AbortError"
  );
}

/**
 * API 失敗を画面の文言に（指示書AY 段階9-2 の表・指示書BJ J1/J2）。
 * ★取り消し（`AbortError`）だけ null★。それ以外の status 0 は通信失敗の文言。
 */
export function apiErrorMessage(e: unknown, t: (text: string) => string): string | null {
  if (!(e instanceof ApiFetchError)) {
    return t("データの取得に失敗しました");
  }
  if (e.status === 0) {
    if (isAbortCause(e.cause)) return null;
    return t("通信に失敗しました。時間をおいて再度お試しください");
  }
  switch (e.code) {
    case "agent_offline": {
      const last = detailStrings(e.details, "last_seen_at")[0];
      const when = last ? formatDateTime(last) : "-";
      return t("制御盤が接続されていません（最終接続: {日時}）").replace("{日時}", when);
    }
    case "agent_timeout":
      return t("制御盤から応答がありません。しばらくしてから再度お試しください");
    case "export_busy":
      return t("この制御盤は別のエクスポートを処理中です");
    case "agent_busy":
      return t("制御盤が混み合っています。しばらくしてから再度お試しください");
    case "agent_error": {
      const code = detailStrings(e.details, "agent_code")[0] ?? "";
      if (code === "result_invalid") {
        return t("制御盤の結果の形が不正です");
      }
      if (code === "too_large") {
        return t("選んだファイルが大きすぎます（1回 {max} まで）").replace(
          "{max}",
          formatFileSize(EXPORT_MAX_BYTES)
        );
      }
      return t("制御盤でエラーが発生しました（{code}）").replace("{code}", code);
    }
    case "validation_failed":
      if (e.serverMessage === EXPORT_FILE_IDS_TOO_LARGE_MESSAGE) {
        return t(EXPORT_FILE_IDS_TOO_LARGE_MESSAGE);
      }
      return e.serverMessage ?? t("データの取得に失敗しました");
    default:
      return e.serverMessage ?? t("データの取得に失敗しました");
  }
}
