import {
  IconPlus,
  IconBrandSlack,
  IconBrandTelegram,
  IconBrandWhatsapp,
  IconBrandGoogleDrive,
  IconTerminal2,
  IconBuildingSkyscraper,
  IconCopy,
  IconCheck,
  IconChevronLeft,
  IconExternalLink,
  IconCircleCheck,
  IconInfoCircle,
} from "@tabler/icons-react";
import React, { useState, useCallback, useEffect } from "react";

import { agentNativePath } from "../api-path.js";
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "../components/ui/tooltip.js";
import { useT } from "../i18n.js";
import {
  useIntegrationStatus,
  type IntegrationStatus,
} from "./useIntegrationStatus.js";
import { isNonPublicWebhookUrl } from "./webhook-url.js";

// ─── Platform config ─────────────────────────────────────────────────────────

interface PlatformInfo {
  id: string;
  label: string;
  icon: React.ComponentType<any>;
  description: string;
  envVars: string[];
  setupSteps: string[];
  docsUrl?: string;
  /** If true, this is a "client" integration (user connects TO the agent) rather than a webhook */
  isClient?: boolean;
}

const PLATFORMS: PlatformInfo[] = [
  {
    id: "slack",
    label: "Slack",
    icon: IconBrandSlack,
    description:
      "@mention the agent in a Slack thread or DM it, and it replies in that thread.",
    envVars: ["SLACK_BOT_TOKEN", "SLACK_SIGNING_SECRET"],
    setupSteps: [
      "At api.slack.com/apps, create an app for your workspace, then under OAuth & Permissions add the bot scopes app_mentions:read, chat:write, channels:history, and im:history",
      "Click Install to Workspace, then copy the Bot User OAuth Token and the Signing Secret (Basic Information → App Credentials) into the two secrets listed below",
      "Under Event Subscriptions, turn events on, paste the webhook URL below as the Request URL, and subscribe to the bot events app_mention and message.im",
      "Invite the bot to a channel, @mention it in a thread, and confirm it replies in that same thread",
      "Running inside a Dispatch workspace instead? Connect Slack from Settings → Messaging there — it stores workspace tokens for you and this page is not needed.",
    ],
    docsUrl: "https://api.slack.com/apps",
  },
  {
    id: "telegram",
    label: "Telegram",
    icon: IconBrandTelegram,
    description: "Chat with your agent via a Telegram bot.",
    envVars: ["TELEGRAM_BOT_TOKEN"],
    setupSteps: [
      "Message @BotFather on Telegram to create a new bot",
      "Copy the bot token into your environment",
      'Click "Setup webhook" below to register automatically',
    ],
  },
  {
    id: "whatsapp",
    label: "WhatsApp",
    icon: IconBrandWhatsapp,
    description: "Connect your agent to WhatsApp Business.",
    envVars: ["WHATSAPP_TOKEN", "WHATSAPP_VERIFY_TOKEN"],
    setupSteps: [
      "Create a Meta Business app at developers.facebook.com",
      "Set up WhatsApp Business API",
      "Configure the webhook URL and verify token",
      "Copy the access token into your environment",
    ],
    docsUrl: "https://developers.facebook.com/docs/whatsapp",
  },
  {
    id: "google-docs",
    label: "Google Docs",
    icon: IconBrandGoogleDrive,
    description: "Tag the agent in Google Doc comments to get responses.",
    envVars: ["GOOGLE_SERVICE_ACCOUNT_KEY"],
    setupSteps: [
      "Create a Google Cloud service account and download the JSON key",
      "Set GOOGLE_SERVICE_ACCOUNT_KEY in your environment (JSON string or file path)",
      "Share your Google Docs with the service account email",
      'Write a comment containing "@Agent" to trigger the agent',
    ],
  },
  {
    id: "openclaw",
    label: "OpenClaw",
    icon: IconTerminal2,
    description: "Access this agent from OpenClaw's unified agent interface.",
    envVars: [],
    isClient: true,
    setupSteps: [
      "Install OpenClaw: npm install -g openclaw",
      "Add this agent's URL as a provider in your OpenClaw config",
      "OpenClaw discovers your agent's capabilities via the A2A protocol",
    ],
  },
  {
    id: "claude-code",
    label: "Claude Code",
    icon: IconTerminal2,
    description:
      "Let Claude Code call this agent via A2A for data and actions.",
    envVars: [],
    isClient: true,
    setupSteps: [
      "Your agent exposes an A2A endpoint at /.well-known/agent-card.json",
      "In Claude Code, reference your agent's URL when asking for data",
      "Claude Code will discover and call your agent's skills automatically",
    ],
  },
  {
    id: "builder",
    label: "Builder.io",
    icon: IconBuildingSkyscraper,
    description:
      "One chat interface that orchestrates all your agents together.",
    envVars: [],
    isClient: true,
    setupSteps: [
      "Connect your agent-native apps in your Builder.io workspace",
      "Builder.io discovers each agent's skills via A2A",
      "Chat with one agent that can trigger actions across all your apps",
    ],
    docsUrl:
      "https://www.builder.io?utm_source=agent-native&utm_medium=product&utm_campaign=integrations&utm_content=integrations_panel",
  },
];

function useAgentEngineConfigured() {
  const [configured, setConfigured] = useState<boolean | undefined>(undefined);

  const refresh = useCallback(() => {
    fetch(agentNativePath("/_agent-native/agent-engine/status"))
      .then((r) => (r.ok ? r.json() : null))
      .then((data) => {
        if (typeof data?.configured === "boolean") {
          setConfigured(data.configured);
        }
      })
      .catch(() => {});
  }, []);

  useEffect(() => {
    refresh();
    window.addEventListener("agent-engine:configured-changed", refresh);
    return () =>
      window.removeEventListener("agent-engine:configured-changed", refresh);
  }, [refresh]);

  return configured;
}

// ─── Integration detail view ─────────────────────────────────────────────────

function IntegrationDetail({
  platform,
  serverStatus,
  onBack,
  onRefresh,
}: {
  platform: PlatformInfo;
  serverStatus?: IntegrationStatus;
  onBack: () => void;
  onRefresh: () => void;
}) {
  const t = useT();
  const [toggling, setToggling] = useState(false);
  const [copied, setCopied] = useState(false);
  const [toggleError, setToggleError] = useState<string | null>(null);
  const agentEngineConfigured = useAgentEngineConfigured();

  const handleToggle = useCallback(async () => {
    setToggling(true);
    setToggleError(null);
    try {
      const action = serverStatus?.enabled ? "disable" : "enable";
      const res = await fetch(
        agentNativePath(`/_agent-native/integrations/${platform.id}/${action}`),
        { method: "POST" },
      );
      if (res.ok) {
        onRefresh();
        return;
      }
      // Surface the real reason instead of silently doing nothing.
      // The endpoint returns `{ error }` for known failures (admin gating,
      // missing secrets, etc.); fall back to status text otherwise.
      const data = (await res.json().catch(() => null)) as {
        error?: string;
      } | null;
      setToggleError(
        data?.error ||
          res.statusText ||
          `Couldn't ${action} ${platform.label} (HTTP ${res.status})`,
      );
    } catch (err) {
      setToggleError(
        err instanceof Error ? err.message : t("integrations.networkError"),
      );
    } finally {
      setToggling(false);
    }
  }, [platform.id, platform.label, serverStatus?.enabled, onRefresh]);

  const handleCopy = useCallback(async (text: string) => {
    await navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  }, []);

  const handleOpenLlmSettings = useCallback(() => {
    window.dispatchEvent(
      new CustomEvent("agent-panel:open-settings", {
        detail: { section: "llm" },
      }),
    );
  }, []);

  const isConfigured = serverStatus?.configured ?? false;
  const isEnabled = serverStatus?.enabled ?? false;
  const showAgentEnginePrereq =
    !platform.isClient && agentEngineConfigured === false;
  const serviceAccountEmail =
    typeof serverStatus?.details?.serviceAccountEmail === "string"
      ? serverStatus.details.serviceAccountEmail
      : null;

  return (
    <div>
      <button
        onClick={onBack}
        className="flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2"
      >
        <IconChevronLeft size={12} className="rtl:-scale-x-100" />
        {t("integrations.back")}
      </button>

      <div className="flex items-center gap-2 mb-2">
        <platform.icon size={18} className="text-foreground shrink-0" />
        <div>
          <div className="text-xs font-medium text-foreground">
            {platform.label}
          </div>
          <div className="text-[10px] text-muted-foreground">
            {platform.description}
          </div>
        </div>
      </div>

      {showAgentEnginePrereq && (
        <div className="mb-3 rounded-md border border-amber-500/30 bg-amber-500/10 px-2.5 py-2">
          <div className="flex items-center justify-between gap-2">
            <div className="min-w-0">
              <div className="text-[10px] font-medium text-foreground">
                {t("integrations.agentEngineRequired")}
              </div>
              <p className="mt-0.5 text-[10px] leading-relaxed text-muted-foreground">
                {t("integrations.agentEngineDescription", {
                  platform: platform.label,
                })}
              </p>
            </div>
            <button
              type="button"
              onClick={handleOpenLlmSettings}
              className="shrink-0 rounded border border-border bg-background px-2 py-1 text-[10px] font-medium text-muted-foreground transition-colors hover:bg-accent/40 hover:text-foreground"
            >
              {t("integrations.openLlm")}
            </button>
          </div>
        </div>
      )}

      {/* Setup steps */}
      <div className="mb-3">
        <div className="text-[10px] font-medium text-muted-foreground mb-1.5">
          {t("integrations.setup")}
        </div>
        <ol className="space-y-1">
          {platform.setupSteps.map((step, i) => (
            <li
              key={i}
              className="flex gap-1.5 text-[10px] text-muted-foreground leading-relaxed"
            >
              <span className="shrink-0 text-muted-foreground/50">
                {i + 1}.
              </span>
              {step}
            </li>
          ))}
        </ol>
      </div>

      {serviceAccountEmail && (
        <div className="mb-3">
          <div className="text-[10px] font-medium text-muted-foreground mb-1">
            {t("integrations.shareDocumentsWith")}
          </div>
          <div className="flex items-center gap-1">
            <code className="flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground">
              {serviceAccountEmail}
            </code>
            <Tooltip>
              <TooltipTrigger asChild>
                <button
                  onClick={() => handleCopy(serviceAccountEmail)}
                  className="shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50"
                >
                  {copied ? <IconCheck size={12} /> : <IconCopy size={12} />}
                </button>
              </TooltipTrigger>
              <TooltipContent>
                {t("integrations.copyServiceAccountEmail")}
              </TooltipContent>
            </Tooltip>
          </div>
        </div>
      )}

      {/* Required secrets */}
      {platform.envVars.length > 0 && (
        <div className="mb-3">
          <div className="text-[10px] font-medium text-muted-foreground mb-1">
            {t("integrations.requiredSecrets")}
          </div>
          <div className="space-y-0.5">
            {platform.envVars.map((v) => (
              <div key={v} className="flex items-center gap-1">
                <code className="text-[10px] text-foreground bg-muted px-1 py-0.5 rounded">
                  {v}
                </code>
                {isConfigured && (
                  <IconCircleCheck
                    size={11}
                    className="text-green-500 shrink-0"
                  />
                )}
              </div>
            ))}
          </div>
          {!isConfigured && (
            <p className="text-[10px] text-amber-500 mt-1">
              {t("integrations.envHelp")}
            </p>
          )}
        </div>
      )}

      {/* Webhook URL */}
      {serverStatus?.webhookUrl && !platform.isClient && (
        <div className="mb-3">
          <div className="text-[10px] font-medium text-muted-foreground mb-1">
            {t("integrations.webhookUrl")}
          </div>
          {isNonPublicWebhookUrl(serverStatus.webhookUrl) ? (
            <div className="flex gap-1.5 rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] leading-relaxed text-muted-foreground">
              <IconInfoCircle size={12} className="mt-px shrink-0" />
              <span>
                {t("integrations.webhookUrlLocalOnly", {
                  platform: platform.label,
                  url: serverStatus.webhookUrl,
                })}
              </span>
            </div>
          ) : (
            <div className="flex items-center gap-1">
              <code className="flex-1 truncate rounded bg-muted px-1.5 py-0.5 text-[10px] text-foreground">
                {serverStatus.webhookUrl}
              </code>
              <Tooltip>
                <TooltipTrigger asChild>
                  <button
                    onClick={() => handleCopy(serverStatus.webhookUrl!)}
                    className="shrink-0 rounded p-0.5 text-muted-foreground hover:text-foreground hover:bg-accent/50"
                  >
                    {copied ? <IconCheck size={12} /> : <IconCopy size={12} />}
                  </button>
                </TooltipTrigger>
                <TooltipContent>{t("integrations.copy")}</TooltipContent>
              </Tooltip>
            </div>
          )}
        </div>
      )}

      {/* Docs link */}
      {platform.docsUrl && (
        <a
          href={platform.docsUrl}
          target="_blank"
          rel="noopener noreferrer"
          className="flex items-center gap-1 text-[10px] text-blue-400 hover:text-blue-300 mb-3"
        >
          {t("integrations.documentation")}
          <IconExternalLink size={10} />
        </a>
      )}

      {/* Enable/disable for server integrations */}
      {serverStatus && !platform.isClient && isConfigured && (
        <button
          onClick={handleToggle}
          disabled={toggling}
          className={`w-full rounded-md border px-2 py-1.5 text-[11px] font-medium disabled:opacity-50 ${
            isEnabled
              ? "border-border text-foreground hover:bg-accent/50"
              : "border-green-600/50 text-green-400 hover:bg-green-900/20"
          }`}
        >
          {toggling
            ? t("integrations.toggling")
            : isEnabled
              ? t("integrations.disable")
              : t("integrations.enable")}
        </button>
      )}

      {/* Status for client integrations */}
      {platform.isClient && (
        <div className="rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground">
          {t("integrations.clientAvailable")}
        </div>
      )}

      {serverStatus?.error && (
        <p className="text-[10px] text-destructive mt-2">
          {serverStatus.error}
        </p>
      )}

      {toggleError && (
        <p className="text-[10px] text-destructive mt-2">{toggleError}</p>
      )}
    </div>
  );
}

// ─── Add integration picker ──────────────────────────────────────────────────

function AddIntegrationPicker({
  connectedIds,
  onSelect,
}: {
  connectedIds: Set<string>;
  onSelect: (platform: PlatformInfo) => void;
}) {
  return (
    <div className="space-y-1">
      {PLATFORMS.filter((p) => !connectedIds.has(p.id)).map((platform) => (
        <button
          key={platform.id}
          onClick={() => onSelect(platform)}
          className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-start hover:bg-accent/50"
        >
          <platform.icon size={14} className="shrink-0 text-muted-foreground" />
          <div className="flex-1 min-w-0">
            <div className="text-[11px] font-medium text-foreground">
              {platform.label}
            </div>
            <div className="text-[10px] text-muted-foreground truncate">
              {platform.description}
            </div>
          </div>
        </button>
      ))}
    </div>
  );
}

// ─── Main panel ──────────────────────────────────────────────────────────────

export function IntegrationsPanel() {
  const t = useT();
  const { statuses, loading, refetch } = useIntegrationStatus();
  const [selectedPlatform, setSelectedPlatform] = useState<PlatformInfo | null>(
    null,
  );
  const [showPicker, setShowPicker] = useState(false);

  const statusMap = new Map(statuses.map((s) => [s.platform, s]));

  // Show connected (enabled or configured) integrations
  const connectedPlatforms = PLATFORMS.filter((p) => {
    const s = statusMap.get(p.id);
    return s?.configured || s?.enabled;
  });

  const connectedIds = new Set(connectedPlatforms.map((p) => p.id));

  if (selectedPlatform) {
    return (
      <IntegrationDetail
        platform={selectedPlatform}
        serverStatus={statusMap.get(selectedPlatform.id)}
        onBack={() => setSelectedPlatform(null)}
        onRefresh={refetch}
      />
    );
  }

  if (showPicker) {
    return (
      <div>
        <button
          onClick={() => setShowPicker(false)}
          className="flex items-center gap-1 text-[10px] text-muted-foreground hover:text-foreground mb-2"
        >
          <IconChevronLeft size={12} className="rtl:-scale-x-100" />
          {t("integrations.back")}
        </button>
        <div className="text-[10px] font-medium text-muted-foreground mb-1.5">
          {t("integrations.addChatIntegration")}
        </div>
        <AddIntegrationPicker
          connectedIds={connectedIds}
          onSelect={(p) => {
            setSelectedPlatform(p);
            setShowPicker(false);
          }}
        />
      </div>
    );
  }

  return (
    <div>
      <div className="flex items-center justify-between mb-1.5">
        <div>
          <div className="text-xs font-medium text-foreground">
            {t("integrations.chatIntegrations")}
          </div>
          <div className="text-[10px] text-muted-foreground">
            {t("integrations.chatIntegrationsDescription")}
          </div>
        </div>
        <div className="flex items-center gap-1">
          <Tooltip>
            <TooltipTrigger asChild>
              <button
                onClick={() => setShowPicker(true)}
                className="flex h-5 w-5 items-center justify-center rounded text-muted-foreground hover:bg-accent/50 hover:text-foreground"
              >
                <IconPlus size={12} />
              </button>
            </TooltipTrigger>
            <TooltipContent>{t("integrations.addIntegration")}</TooltipContent>
          </Tooltip>
        </div>
      </div>

      {loading ? (
        <div className="space-y-1.5">
          <div className="h-6 w-full rounded bg-muted/50 animate-pulse" />
          <div className="h-6 w-3/4 rounded bg-muted/50 animate-pulse" />
        </div>
      ) : connectedPlatforms.length === 0 ? (
        <div className="space-y-2">
          <button
            onClick={() => setShowPicker(true)}
            className="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/30"
          >
            <IconPlus size={12} className="shrink-0" />
            {t("integrations.addIntegration")}
          </button>
          <div className="rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground">
            {t("integrations.dispatchEntrypoint")}{" "}
            <a
              href="https://dispatch.agent-native.com"
              target="_blank"
              rel="noopener noreferrer"
              className="no-underline font-medium text-foreground hover:text-foreground/80"
            >
              dispatch template
            </a>
            .
          </div>
        </div>
      ) : (
        <div className="space-y-2">
          {connectedPlatforms.map((platform) => {
            const s = statusMap.get(platform.id);
            return (
              <button
                key={platform.id}
                onClick={() => setSelectedPlatform(platform)}
                className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-start hover:bg-accent/50"
              >
                <platform.icon
                  size={14}
                  className="shrink-0 text-muted-foreground"
                />
                <span className="flex-1 text-[11px] font-medium text-foreground truncate">
                  {platform.label}
                </span>
                {s && (
                  <span
                    className={`inline-block h-1.5 w-1.5 rounded-full shrink-0 ${
                      s.enabled && s.configured
                        ? "bg-green-500"
                        : s.configured
                          ? "bg-yellow-500"
                          : "bg-muted-foreground/55"
                    }`}
                  />
                )}
              </button>
            );
          })}
          <div className="rounded-md border border-border bg-muted/30 px-2.5 py-2 text-[10px] text-muted-foreground">
            {t("integrations.sharedMessaging")}
          </div>
        </div>
      )}
    </div>
  );
}
