import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
import { normalizeE164 } from "openclaw/plugin-sdk/account-resolution";
import {
  adaptScopedAccountAccessor,
  createScopedChannelConfigAdapter,
  createScopedDmSecurityResolver,
  formatWhatsAppConfigAllowFromEntries,
} from "openclaw/plugin-sdk/channel-config-helpers";
import { createAllowlistProviderRouteAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy";
import { createChannelPluginBase, getChatChannelMeta } from "openclaw/plugin-sdk/core";
import type { ChannelPlugin } from "openclaw/plugin-sdk/core";
import {
  createDelegatedSetupWizardProxy,
  type ChannelSetupWizard,
} from "openclaw/plugin-sdk/setup";
import {
  listWhatsAppAccountIds,
  resolveDefaultWhatsAppAccountId,
  resolveWhatsAppAccount,
  hasAnyWhatsAppAuth,
  type ResolvedWhatsAppAccount,
} from "./accounts.js";
import { WhatsAppChannelConfigSchema } from "./config-schema.js";
import { whatsappDoctor } from "./doctor.js";
import { resolveWhatsAppGroupIntroHint } from "./group-intro.js";
import {
  resolveWhatsAppGroupRequireMention,
  resolveWhatsAppGroupToolPolicy,
} from "./group-policy.js";

export const WHATSAPP_CHANNEL = "whatsapp" as const;

export async function loadWhatsAppChannelRuntime() {
  return await import("./channel.runtime.js");
}

export const whatsappSetupWizardProxy = createWhatsAppSetupWizardProxy(
  async () => (await loadWhatsAppChannelRuntime()).whatsappSetupWizard,
);

const whatsappConfigAdapter = createScopedChannelConfigAdapter<ResolvedWhatsAppAccount>({
  sectionKey: WHATSAPP_CHANNEL,
  listAccountIds: listWhatsAppAccountIds,
  resolveAccount: adaptScopedAccountAccessor(resolveWhatsAppAccount),
  defaultAccountId: resolveDefaultWhatsAppAccountId,
  clearBaseFields: [],
  allowTopLevel: false,
  resolveAllowFrom: (account) => account.allowFrom,
  formatAllowFrom: (allowFrom) => formatWhatsAppConfigAllowFromEntries(allowFrom),
  resolveDefaultTo: (account) => account.defaultTo,
});

const whatsappResolveDmPolicy = createScopedDmSecurityResolver<ResolvedWhatsAppAccount>({
  channelKey: WHATSAPP_CHANNEL,
  resolvePolicy: (account) => account.dmPolicy,
  resolveAllowFrom: (account) => account.allowFrom,
  policyPathSuffix: "dmPolicy",
  normalizeEntry: (raw) => normalizeE164(raw),
});

export function createWhatsAppSetupWizardProxy(
  loadWizard: () => Promise<ChannelSetupWizard>,
): ChannelSetupWizard {
  return createDelegatedSetupWizardProxy({
    channel: WHATSAPP_CHANNEL,
    loadWizard,
    status: {
      configuredLabel: "linked",
      unconfiguredLabel: "not linked",
      configuredHint: "linked",
      unconfiguredHint: "not linked",
      configuredScore: 5,
      unconfiguredScore: 4,
    },
    resolveShouldPromptAccountIds: (params) =>
      (params.shouldPromptAccountIds || params.options?.promptWhatsAppAccountId) ?? false,
    credentials: [],
    delegateFinalize: true,
    disable: (cfg) => ({
      ...cfg,
      channels: {
        ...cfg.channels,
        whatsapp: {
          ...cfg.channels?.whatsapp,
          enabled: false,
        },
      },
    }),
    onAccountRecorded: (accountId, options) => {
      options?.onWhatsAppAccountId?.(accountId);
    },
  });
}

export function createWhatsAppPluginBase(params: {
  groups: NonNullable<ChannelPlugin<ResolvedWhatsAppAccount>["groups"]>;
  setupWizard: NonNullable<ChannelPlugin<ResolvedWhatsAppAccount>["setupWizard"]>;
  setup: NonNullable<ChannelPlugin<ResolvedWhatsAppAccount>["setup"]>;
  isConfigured: NonNullable<ChannelPlugin<ResolvedWhatsAppAccount>["config"]>["isConfigured"];
}) {
  const collectWhatsAppSecurityWarnings =
    createAllowlistProviderRouteAllowlistWarningCollector<ResolvedWhatsAppAccount>({
      providerConfigPresent: (cfg) => cfg.channels?.whatsapp !== undefined,
      resolveGroupPolicy: (account) => account.groupPolicy,
      resolveRouteAllowlistConfigured: (account) =>
        Boolean(account.groups) && Object.keys(account.groups ?? {}).length > 0,
      restrictSenders: {
        surface: "WhatsApp groups",
        openScope: "any member in allowed groups",
        groupPolicyPath: "channels.whatsapp.groupPolicy",
        groupAllowFromPath: "channels.whatsapp.groupAllowFrom",
      },
      noRouteAllowlist: {
        surface: "WhatsApp groups",
        routeAllowlistPath: "channels.whatsapp.groups",
        routeScope: "group",
        groupPolicyPath: "channels.whatsapp.groupPolicy",
        groupAllowFromPath: "channels.whatsapp.groupAllowFrom",
      },
    });
  const base = createChannelPluginBase({
    id: WHATSAPP_CHANNEL,
    meta: {
      ...getChatChannelMeta(WHATSAPP_CHANNEL),
      showConfigured: false,
      quickstartAllowFrom: true,
      forceAccountBinding: true,
      preferSessionLookupForAnnounceTarget: true,
    },
    setupWizard: params.setupWizard,
    capabilities: {
      chatTypes: ["direct", "group"],
      polls: true,
      reactions: true,
      media: true,
    },
    reload: { configPrefixes: ["web"], noopPrefixes: ["channels.whatsapp"] },
    gatewayMethods: ["web.login.start", "web.login.wait"],
    configSchema: WhatsAppChannelConfigSchema,
    config: {
      ...whatsappConfigAdapter,
      isEnabled: (account, cfg) => account.enabled && cfg.web?.enabled !== false,
      disabledReason: () => "disabled",
      isConfigured: params.isConfigured,
      hasPersistedAuthState: ({ cfg }) => hasAnyWhatsAppAuth(cfg),
      unconfiguredReason: () => "not linked",
      describeAccount: (account) =>
        describeAccountSnapshot({
          account,
          configured: Boolean(account.authDir),
          extra: {
            linked: Boolean(account.authDir),
            dmPolicy: account.dmPolicy,
            allowFrom: account.allowFrom,
          },
        }),
    },
    security: {
      resolveDmPolicy: whatsappResolveDmPolicy,
      collectWarnings: collectWhatsAppSecurityWarnings,
    },
    doctor: whatsappDoctor,
    setup: params.setup,
    groups: params.groups,
  });
  return {
    ...base,
    setupWizard: base.setupWizard!,
    capabilities: base.capabilities!,
    reload: base.reload!,
    gatewayMethods: base.gatewayMethods!,
    configSchema: base.configSchema!,
    config: base.config!,
    security: base.security!,
    groups: base.groups!,
  } satisfies Pick<
    ChannelPlugin<ResolvedWhatsAppAccount>,
    | "id"
    | "meta"
    | "setupWizard"
    | "capabilities"
    | "reload"
    | "gatewayMethods"
    | "configSchema"
    | "config"
    | "security"
    | "doctor"
    | "setup"
    | "groups"
  >;
}
