// agent = openclaw channel account.
// Config shape:
//   channels.fabric.centerApiBase = "http://localhost:7001/api"   (shared)
//   channels.fabric.accounts.<agentId> = { fabricApiKey, centerApiBase? }
// Each account id IS the openclaw agentId that owns that Fabric identity.

export type FabricAccountConfig = {
  fabricApiKey?: string;
  centerApiBase?: string;
  enabled?: boolean;
  allowFrom?: string[];
  dmPolicy?: string;
};

export type FabricChannelConfig = {
  centerApiBase?: string;
  // Shared secret matching the guild's FABRIC_BACKEND_GUILD_COMMANDS_SYNC_KEY
  // (Guild C-2). Required by the channel config schema; sourced from config
  // only — never from the environment.
  commandsSyncKey?: string;
  // Coalesce an agent turn that OpenClaw split into multiple deliveries
  // (text → thinking/tool → text => N sendText calls) into ONE Fabric
  // message. The flush boundary is the deterministic `agent_end` hook (not
  // a timer). Default true; set false for raw per-segment posting.
  coalesce?: boolean;
  accounts?: Record<string, FabricAccountConfig>;
  defaultAccount?: string;
} & FabricAccountConfig;

type Cfg = { channels?: { fabric?: FabricChannelConfig }; [k: string]: unknown };

export type ResolvedFabricAccount = {
  accountId: string;
  enabled: boolean;
  centerApiBase: string;
  fabricApiKey: string;
  allowFrom: string[];
  dmPolicy: string | undefined;
};

const DEFAULT_CENTER = 'http://localhost:7001/api';

function section(cfg: Cfg): FabricChannelConfig {
  return cfg.channels?.fabric ?? {};
}

// The commands-sync shared secret (channel-level only). Empty string when
// unconfigured — callers decide how to handle (slash-command sync is then
// rejected by the guild).
export function resolveCommandsSyncKey(cfg: Cfg): string {
  return (section(cfg).commandsSyncKey ?? '').trim();
}

// Whether to coalesce a split agent turn into one Fabric message
// (channel-level). Default true.
export function resolveCoalesce(cfg: Cfg): boolean {
  return (cfg.channels?.fabric ?? {}).coalesce !== false;
}

export function listFabricAccountIds(cfg: Cfg): string[] {
  const accts = section(cfg).accounts ?? {};
  const ids = Object.keys(accts);
  return ids.length ? ids : ['default'];
}

export function resolveDefaultFabricAccountId(cfg: Cfg): string {
  const s = section(cfg);
  if (s.defaultAccount) return s.defaultAccount;
  const ids = listFabricAccountIds(cfg);
  return ids[0] ?? 'default';
}

export function resolveFabricAccount(cfg: Cfg, accountId?: string | null): ResolvedFabricAccount {
  const s = section(cfg);
  const id = accountId ?? resolveDefaultFabricAccountId(cfg);
  const acc = s.accounts?.[id] ?? {};
  const fabricApiKey = (acc.fabricApiKey ?? '').trim();
  const centerApiBase = (acc.centerApiBase ?? s.centerApiBase ?? DEFAULT_CENTER).trim();
  return {
    accountId: id,
    enabled: acc.enabled !== false && s.enabled !== false,
    centerApiBase,
    fabricApiKey,
    allowFrom: acc.allowFrom ?? s.allowFrom ?? [],
    dmPolicy: acc.dmPolicy ?? s.dmPolicy,
  };
}

export function listEnabledFabricAccounts(cfg: Cfg): ResolvedFabricAccount[] {
  return listFabricAccountIds(cfg)
    .map((id) => resolveFabricAccount(cfg, id))
    .filter((a) => a.enabled && a.fabricApiKey);
}
