import { isOptionalApiRouteMissing } from "./apiErrorUtils";
import { isRecord, serverRequest } from "./serverConnection";

export interface ModelCapabilityOption {
  value: string;
  label: string;
  description?: string;
  badge?: string;
  enabled?: boolean;
  status?: "available" | "maintenance" | "disabled" | string;
}

export interface WebModelCapabilities {
  source: "server" | "fallback";
  imageModels: ModelCapabilityOption[];
  videoModels: ModelCapabilityOption[];
  chatModels: ModelCapabilityOption[];
  updatedAt?: string;
}

function toStringValue(value: unknown, fallback = ""): string {
  if (typeof value === "string") return value.trim() || fallback;
  if (typeof value === "number" && Number.isFinite(value)) return String(value);
  return fallback;
}

function normalizeModelOption(raw: unknown): ModelCapabilityOption | null {
  if (typeof raw === "string") {
    const value = raw.trim();
    return value ? { value, label: value } : null;
  }
  if (!isRecord(raw)) return null;

  const value = toStringValue(raw.value ?? raw.id ?? raw.model ?? raw.modelKey ?? raw.model_key);
  if (!value) return null;

  const status = toStringValue(raw.status);
  const enabled = raw.enabled === undefined ? status !== "maintenance" && status !== "disabled" : Boolean(raw.enabled);
  if (!enabled) return null;

  const label = toStringValue(raw.label ?? raw.displayName ?? raw.display_name ?? raw.name, value);

  return {
    value,
    label:
      value === "wan2.7-image-pro"
        ? label.replace(/\s*4k\b/i, "").trim() || "wan 2.7 Pro"
        : label,
    description: toStringValue(raw.description) || undefined,
    badge: toStringValue(raw.badge) || undefined,
    enabled,
    status: status || "available",
  };
}

function normalizeModelList(value: unknown): ModelCapabilityOption[] {
  if (!Array.isArray(value)) return [];
  const options: ModelCapabilityOption[] = [];
  for (const item of value) {
    const option = normalizeModelOption(item);
    if (option) options.push(option);
  }
  return options;
}

function createFallbackCapabilities(): WebModelCapabilities {
  return {
    source: "fallback",
    imageModels: [],
    videoModels: [],
    chatModels: [],
  };
}

let modelCapabilitiesRouteMissing = false;

export const modelCapabilitiesClient = {
  async get(name = "web-model-capabilities"): Promise<WebModelCapabilities> {
    if (modelCapabilitiesRouteMissing) return createFallbackCapabilities();

    let payload: unknown;
    try {
      payload = await serverRequest<unknown>(`public/config/profile?name=${encodeURIComponent(name)}`);
    } catch (error) {
      if (isOptionalApiRouteMissing(error)) {
        modelCapabilitiesRouteMissing = true;
        return createFallbackCapabilities();
      }
      throw error;
    }

    const raw = isRecord(payload) && isRecord(payload.config) ? payload.config : payload;
    const config = isRecord(raw) ? raw : {};
    const models = isRecord(config.models) ? config.models : {};

    return {
      source: "server",
      imageModels: normalizeModelList(config.imageModels ?? config.image_models ?? models.image),
      videoModels: normalizeModelList(config.videoModels ?? config.video_models ?? models.video),
      chatModels: normalizeModelList(config.chatModels ?? config.chat_models ?? models.chat ?? models.agent ?? models.text),
      updatedAt: toStringValue((payload as { updatedAt?: unknown; updated_at?: unknown })?.updatedAt ?? (payload as { updated_at?: unknown })?.updated_at),
    };
  },
};
