import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import {
  adaptScopedAccountAccessor,
  createScopedChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
import {
  buildChannelConfigSchema,
  getChatChannelMeta,
  normalizeAccountId,
  TelegramConfigSchema,
  type ChannelPlugin,
  type OpenClawConfig,
} from "../runtime-api.js";
import { inspectTelegramAccount } from "./account-inspect.js";
import {
  listTelegramAccountIds,
  resolveDefaultTelegramAccountId,
  resolveTelegramAccount,
  type ResolvedTelegramAccount,
} from "./accounts.js";

export const TELEGRAM_CHANNEL = "telegram" as const;

export function findTelegramTokenOwnerAccountId(params: {
  cfg: OpenClawConfig;
  accountId: string;
}): string | null {
  const normalizedAccountId = normalizeAccountId(params.accountId);
  const tokenOwners = new Map<string, string>();
  for (const id of listTelegramAccountIds(params.cfg)) {
    const account = inspectTelegramAccount({ cfg: params.cfg, accountId: id });
    const token = (account.token ?? "").trim();
    if (!token) {
      continue;
    }
    const ownerAccountId = tokenOwners.get(token);
    if (!ownerAccountId) {
      tokenOwners.set(token, account.accountId);
      continue;
    }
    if (account.accountId === normalizedAccountId) {
      return ownerAccountId;
    }
  }
  return null;
}

export function formatDuplicateTelegramTokenReason(params: {
  accountId: string;
  ownerAccountId: string;
}): string {
  return (
    `Duplicate Telegram bot token: account "${params.accountId}" shares a token with ` +
    `account "${params.ownerAccountId}". Keep one owner account per bot token.`
  );
}

export const telegramConfigAdapter = createScopedChannelConfigAdapter<ResolvedTelegramAccount>({
  sectionKey: TELEGRAM_CHANNEL,
  listAccountIds: listTelegramAccountIds,
  resolveAccount: adaptScopedAccountAccessor(resolveTelegramAccount),
  inspectAccount: adaptScopedAccountAccessor(inspectTelegramAccount),
  defaultAccountId: resolveDefaultTelegramAccountId,
  clearBaseFields: ["botToken", "tokenFile", "name"],
  resolveAllowFrom: (account: ResolvedTelegramAccount) => account.config.allowFrom,
  formatAllowFrom: (allowFrom) =>
    formatAllowFromLowercase({ allowFrom, stripPrefixRe: /^(telegram|tg):/i }),
  resolveDefaultTo: (account: ResolvedTelegramAccount) => account.config.defaultTo,
});

export function createTelegramPluginBase(params: {
  setupWizard: NonNullable<ChannelPlugin<ResolvedTelegramAccount>["setupWizard"]>;
  setup: NonNullable<ChannelPlugin<ResolvedTelegramAccount>["setup"]>;
}): Pick<
  ChannelPlugin<ResolvedTelegramAccount>,
  "id" | "meta" | "setupWizard" | "capabilities" | "reload" | "configSchema" | "config" | "setup"
> {
  return createChannelPluginBase({
    id: TELEGRAM_CHANNEL,
    meta: {
      ...getChatChannelMeta(TELEGRAM_CHANNEL),
      quickstartAllowFrom: true,
    },
    setupWizard: params.setupWizard,
    capabilities: {
      chatTypes: ["direct", "group", "channel", "thread"],
      reactions: true,
      threads: true,
      media: true,
      polls: true,
      nativeCommands: true,
      blockStreaming: true,
    },
    reload: { configPrefixes: ["channels.telegram"] },
    configSchema: buildChannelConfigSchema(TelegramConfigSchema),
    config: {
      ...telegramConfigAdapter,
      isConfigured: (account, cfg) => {
        if (!account.token?.trim()) {
          return false;
        }
        return !findTelegramTokenOwnerAccountId({ cfg, accountId: account.accountId });
      },
      unconfiguredReason: (account, cfg) => {
        if (!account.token?.trim()) {
          return "not configured";
        }
        const ownerAccountId = findTelegramTokenOwnerAccountId({
          cfg,
          accountId: account.accountId,
        });
        if (!ownerAccountId) {
          return "not configured";
        }
        return formatDuplicateTelegramTokenReason({
          accountId: account.accountId,
          ownerAccountId,
        });
      },
      describeAccount: (account, cfg) => ({
        accountId: account.accountId,
        name: account.name,
        enabled: account.enabled,
        configured:
          Boolean(account.token?.trim()) &&
          !findTelegramTokenOwnerAccountId({ cfg, accountId: account.accountId }),
        tokenSource: account.tokenSource,
      }),
    },
    setup: params.setup,
  }) as Pick<
    ChannelPlugin<ResolvedTelegramAccount>,
    "id" | "meta" | "setupWizard" | "capabilities" | "reload" | "configSchema" | "config" | "setup"
  >;
}
