/**
 * 後端 envelope code / data.message → 語言包。
 * 顯示時一律用目前 UI 語系，不直接秀後端英文。
 */

import { useCallback } from "react";
import { useI18n } from "../i18n/I18nContext";
import { translate } from "./i18n/messages";
import { loadUiPrefs } from "./i18n/prefs";
import type { AppLocale } from "./i18n/types";
import { sanitizeReviewCopy } from "./reviewCopy";

/** 與 backend internal/response + middleware 對齊 */
export const API_CODES = {
  SUCCESS: 102000,
  BAD_REQUEST: 400001,
  WEAK_PASSWORD: 400003,
  INVALID_CODE: 400004,
  SELF_SUSPEND: 400020,
  LAST_ADMIN: 400021,
  MISSING_AUTH: 401001,
  INVALID_TOKEN: 401002,
  MEMBER_NOT_FOUND_AUTH: 401003,
  BAD_PASSWORD: 401010,
  SUSPENDED: 403001,
  ADMIN_REQUIRED: 403002,
  NOT_FOUND: 404001,
  EMAIL_NOT_REGISTERED: 404002,
  EMAIL_TAKEN: 409001,
  QUOTA: 402001,
  METER_CAP: 402002,
  PLATFORM_CAPACITY: 503002,
  SERVER: 500000,
  NOT_IMPLEMENTED: 501000,
  /** demand-radar：路由已在、能力未實作（radar/crm domain.ErrNotReady） */
  CAPABILITY_NOT_READY: 501010,
  /** demand-radar：輸入不合契約（radar/crm domain.ErrValidation） */
  RADAR_VALIDATION: 400100,
  NETWORK: 0,
} as const;

/** code → messages.ts 的 key */
export const API_ERROR_I18N_KEY: Record<number, string> = {
  [API_CODES.BAD_REQUEST]: "api.err.400001",
  [API_CODES.WEAK_PASSWORD]: "api.err.400003",
  [API_CODES.INVALID_CODE]: "api.err.400004",
  [API_CODES.SELF_SUSPEND]: "api.err.400020",
  [API_CODES.LAST_ADMIN]: "api.err.400021",
  [API_CODES.MISSING_AUTH]: "api.err.401001",
  [API_CODES.INVALID_TOKEN]: "api.err.401002",
  [API_CODES.MEMBER_NOT_FOUND_AUTH]: "api.err.401003",
  [API_CODES.BAD_PASSWORD]: "api.err.401010",
  [API_CODES.SUSPENDED]: "api.err.403001",
  [API_CODES.ADMIN_REQUIRED]: "api.err.403002",
  [API_CODES.NOT_FOUND]: "api.err.404001",
  [API_CODES.EMAIL_NOT_REGISTERED]: "api.err.404002",
  [API_CODES.EMAIL_TAKEN]: "api.err.409001",
  [API_CODES.QUOTA]: "api.err.402001",
  [API_CODES.METER_CAP]: "usage.err.meterCap",
  [API_CODES.PLATFORM_CAPACITY]: "usage.err.platformCapacity",
  [API_CODES.SERVER]: "api.err.500000",
  [API_CODES.NOT_IMPLEMENTED]: "api.err.501000",
  [API_CODES.CAPABILITY_NOT_READY]: "api.err.501010",
  [API_CODES.RADAR_VALIDATION]: "api.err.400100",
  [API_CODES.NETWORK]: "api.err.network",
  // 400050/400060 不進表：後端 message 常是具體中文原因（人設分析等），由 rawMessage 顯示
  400061: "api.err.crawlerSession",
  503001: "api.err.timeoutAI",
  // 503002 = PLATFORM_CAPACITY，已在上方 API_CODES 映射
};

export function i18nKeyForApiCode(code: number): string | undefined {
  return API_ERROR_I18N_KEY[code];
}

/**
 * 後端 data.message（英文固定字）→ 語言包 key。
 * 對齊 apps/backend internal/logic/** 回傳的 Message 字串。
 */
const API_OK_MESSAGE_KEY: Record<string, string> = {
  "verification code sent": "api.ok.verifySent",
  "verification code issued": "api.ok.verifyIssued",
  "reset code sent": "api.ok.resetSent",
  "password updated": "api.ok.passwordUpdated",
  "logged out": "api.ok.loggedOut",
  "unbound": "api.ok.unbound",
  // 舊文案相容
  "if the account exists, a reset code was issued": "api.ok.resetSent",
};

export function i18nKeyForApiOkMessage(raw: string): string | undefined {
  const k = raw.trim().toLowerCase();
  if (!k) return undefined;
  // exact
  if (API_OK_MESSAGE_KEY[raw.trim()]) return API_OK_MESSAGE_KEY[raw.trim()];
  if (API_OK_MESSAGE_KEY[k]) return API_OK_MESSAGE_KEY[k];
  // case-insensitive scan
  for (const [en, key] of Object.entries(API_OK_MESSAGE_KEY)) {
    if (en.toLowerCase() === k) return key;
  }
  return undefined;
}

/** 成功 data.message → 目前語系文案；未知則回原文或 fallbackKey */
export function messageForApiOk(
  raw: string | undefined | null,
  fallbackKey = "common.success",
  locale?: AppLocale,
): string {
  const loc = locale ?? currentLocale();
  const text = (raw || "").trim();
  if (!text) return translate(loc, fallbackKey);
  const key = i18nKeyForApiOkMessage(text);
  if (key) return translate(loc, key);
  return sanitizeReviewCopy(text, loc);
}

function currentLocale(): AppLocale {
  try {
    return loadUiPrefs().locale;
  } catch {
    return "zh-TW";
  }
}

/** 後端業務提示（多為中文）可直接顯示，避免被「操作失敗」蓋掉 */
function cleanBizMessage(raw: string): string {
  let s = raw.trim();
  for (const p of ["studio validation: ", "inspire validation: ", "scout validation: ", "validation: "]) {
    if (s.toLowerCase().startsWith(p)) {
      s = s.slice(p.length).trim();
      break;
    }
  }
  // errors.Is wrap: "studio validation: detail"
  const m = s.match(/^(?:studio|inspire|scout)\s+validation:\s*(.+)$/i);
  if (m?.[1]) s = m[1].trim();
  return s;
}

function isUserFacingBizMessage(raw: string | undefined | null): boolean {
  const s = (raw || "").trim();
  if (!s) return false;
  // 含中日韓或明確業務提示
  if (/[\u4e00-\u9fff]/.test(s)) return true;
  if (s.length >= 24 && !/^error\b/i.test(s)) return true;
  return false;
}

/**
 * 依業務碼 + 目前語系取文案（給非 React 層，如 http client）。
 * 已知 code 用語言包；否則若 fallback 是可讀業務提示則直接顯示。
 */
export function messageForApiCode(
  code: number,
  fallback?: string,
  locale?: AppLocale,
): string {
  const loc = locale ?? currentLocale();
  // 後端業務錯誤直接回 i18n key（invite.err.* / usage.err.*）
  const fb = (fallback || "").trim();
  if (fb.startsWith("invite.err.") || fb.startsWith("usage.err.")) return translate(loc, fb);
  const key = i18nKeyForApiCode(code);
  if (key) return translate(loc, key);
  if (isUserFacingBizMessage(fallback)) return cleanBizMessage(fallback!);
  return translate(loc, "api.err.unknown");
}

type ErrLike = {
  code?: number;
  message?: string;
  name?: string;
  rawMessage?: string;
};

/** 從 thrown value 取可顯示字串（依目前語言包） */
export function formatThrownError(err: unknown, fallbackKey = "common.error"): string {
  const loc = currentLocale();
  return sanitizeReviewCopy(formatThrownErrorRaw(err, fallbackKey), loc);
}

function formatThrownErrorRaw(err: unknown, fallbackKey = "common.error"): string {
  const loc = currentLocale();
  const e = err as ErrLike | null;
  if (e && typeof e === "object" && e.name === "ApiError") {
    const code = e.code != null ? Number(e.code) : NaN;
    const raw = e.rawMessage || e.message;
    if (typeof raw === "string" && (raw.startsWith("invite.err.") || raw.startsWith("usage.err."))) {
      return translate(loc, raw);
    }
    if (!Number.isNaN(code)) {
      const key = i18nKeyForApiCode(code);
      // 驗證類業務碼：優先後端中文原因
      if (
        isUserFacingBizMessage(raw) &&
        // 400100（radar／crm 驗證）的後端 message 會指到欄位與原因，
        // 例如「services[0].name required」，比通用句對使用者有用得多。
        (code === 400050 || code === 400060 || code === 400061 || code === 400100 || !key)
      ) {
        return cleanBizMessage(String(raw));
      }
      if (key) return translate(loc, key);
    }
    if (isUserFacingBizMessage(raw)) return cleanBizMessage(String(raw));
    return translate(loc, "api.err.unknown");
  }
  if (e && typeof e === "object" && e.code != null && !Number.isNaN(Number(e.code))) {
    const code = Number(e.code);
    const key = i18nKeyForApiCode(code);
    if (key) return translate(loc, key);
    if (isUserFacingBizMessage(e.message)) return cleanBizMessage(String(e.message));
    return translate(loc, "api.err.unknown");
  }
  // mock 前端 throw 的中文 Error，或無 code 的例外
  if (err instanceof Error && err.message && err.name !== "ApiError") {
    return err.message;
  }
  return translate(loc, fallbackKey);
}

/**
 * React hook：用目前 I18n 語言包（t / locale）格式化錯誤。
 * 頁面 catch 請用這個，確保跟 UI 語系完全一致。
 */
export function useFormatApiError() {
  const { locale } = useI18n();
  return useCallback(
    (err: unknown, fallbackKey = "common.error"): string => {
      void locale;
      return formatThrownError(err, fallbackKey);
    },
    [locale],
  );
}

/**
 * React hook：後端成功 message → 目前語言包。
 * 例：verification code sent → 「驗證碼已寄出」
 */
export function useFormatApiOk() {
  const { t, locale } = useI18n();
  return useCallback(
    (raw: string | undefined | null, fallbackKey = "common.success"): string => {
      const text = (raw || "").trim();
      if (!text) return t(fallbackKey);
      const key = i18nKeyForApiOkMessage(text);
      if (key) return t(key);
      return sanitizeReviewCopy(text, locale);
    },
    [t, locale],
  );
}
