provider-config-card.tsx119.6 KBView on GitHub
'use client';

/**
 * Provider Configuration Card
 *
 * A reusable component for configuring provider credentials.
 * Supports both admin mode (org-level credentials) and user mode (personal connections).
 */

import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';
import {
  Check,
  CheckCircle,
  ChevronDown,
  ChevronsUpDown,
  ChevronUp,
  Copy,
  Eye,
  EyeOff,
  ExternalLink,
  Loader2,
  Plus,
  Settings,
  Trash2,
  X,
} from 'lucide-react';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@/components/ui/command';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import type { ProviderId } from '../../../server/src/services/integrations/constants';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type { IntegrationInfo } from '@/modules/aop/constants';
import { useSession } from '@/modules/auth/utils/auth-client';
import { useTRPC } from '@/providers/query-provider';
import { useState, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
import { Badge } from '@/components/ui/badge';
import { Checkbox } from '@/components/ui/checkbox';
import { toast } from 'sonner';
import { getAvailableCedarFields } from '@/modules/crm/utils';
import {
  DATE_FORMAT_OPTIONS,
  type FieldMapping,
  isSimpleMapping,
  isComplexMapping,
  normalizeFieldMappings,
  extractPicklistValues,
  extractPicklistOptions,
} from './field-mapping-utils';

/**
 * Minimal shape of an org default AOP config consumed by this card — only
 * `customFieldDefinitions` is read, to derive the available Cedar field list.
 */
type OrgDefaultAopConfig = {
  customFieldDefinitions?: Record<string, unknown> | null;
};

interface ConnectionField {
  key=[redacted];
  label: string;
  type: 'text' | 'password';
  placeholder: string;
}

interface ProviderConfigCardProps {
  /** Provider ID (e.g., 'gong', 'hubspot') */
  providerId: string;
  /** Integration display info */
  integrationInfo: IntegrationInfo;
  /** Mode: admin for org-level config, user for personal connections */
  mode: 'admin' | 'user';
  /** Current org provider config (admin mode only) */
  orgConfig?: {
    type: 'api_key' | 'oauth' | 'service_account' | 'manual';
    hasCredentials?: boolean;
    isInstalled?: boolean;
    isEnabled?: boolean; // For manual connection types
    adminUserId?: string;
    installedAt?: string;
    userMustAuthenticate?: boolean;
    displayName?: string;
    // CRM-specific defaults
    defaultFieldMappings?: FieldMapping[];
    defaultPeriodicDealSyncEnabled?: boolean;
    defaultExternalCrmPushEnabled?: boolean;
    defaultDealSyncFilter?: Record<string, string>;
    defaultCustomObjectConfig?: {
      object_name: string;
      filter_field: string;
      fields?: string[];
      limit?: number;
    } | null;
  };
  /** Integration capabilities from integrations.list */
  capabilities?: {
    connectionType?: 'oauth' | 'api_key' | 'manual';
    connectionFields?: ConnectionField[];
    apiKeyInstructions?: string;
    webhookScope?: 'org' | 'user' | 'none';
    webhookSetupInstructions?: string;
    hasCreateWebhook?: boolean;
    // CRM-specific
    hasUpdateOpportunityFields?: boolean;
    defaultWriteFieldMappings?: FieldMapping[];
  };
  /** Integration type (crm, meeting, communication) */
  integrationType?: 'crm' | 'meeting' | 'communication';
  /** Whether this provider is connected (user mode) */
  isConnected?: boolean;
  /** Callback when configuration is saved */
  onConfigured?: () => void;
  /** Callback when configuration is removed */
  onRemoved?: () => void;
  /** Organization ID for super admin mode - when set, uses cedarAdmin mutations */
  superAdminOrgId?: string;
  /** Organization default AOP configs for extracting custom fields (admin mode only) */
  orgDefaultAopConfigs?: OrgDefaultAopConfig[];
  /** Use full page for configuration instead of dialog (admin mode only) */
  useFullPageConfig?: boolean;
  /** Brand color for styling buttons (admin mode only) */
  brandColor?: string;
}

export function ProviderConfigCard({
  providerId,
  integrationInfo,
  mode,
  orgConfig,
  capabilities,
  integrationType,
  isConnected,
  onConfigured,
  onRemoved,
  superAdminOrgId,
  orgDefaultAopConfigs,
  useFullPageConfig = false,
  brandColor,
}: ProviderConfigCardProps) {
  const trpc = useTRPC();

  // Helper to determine if text should be white or black based on background color
  const getContrastTextColor = (hexColor: string): string => {
    // Remove # if present
    const hex = hexColor.replace('#', '');
    const r = parseInt(hex.substring(0, 2), 16);
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);
    // Calculate relative luminance - use 0.6 threshold to prefer white text on medium colors
    const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
    return luminance > 0.6 ? '#000000' : '#ffffff';
  };
  const queryClient = useQueryClient();
  const { data: session } = useSession();
  const navigate = useNavigate();

  // UI State
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [showInstructions, setShowInstructions] = useState(false);
  const [showPasswords, setShowPasswords] = useState<Record<string, boolean>>({});
  const [isSaving, setIsSaving] = useState(false);
  const [isRemoving, setIsRemoving] = useState(false);
  const [isInstalling, setIsInstalling] = useState(false);
  const [copiedWebhookUrl, setCopiedWebhookUrl] = useState(false);
  const [isCreatingWebhook, setIsCreatingWebhook] = useState(false);

  // Form state
  const [formFields, setFormFields] = useState<Record<string, string>>({});

  // CRM settings state
  const [showCrmSettings, setShowCrmSettings] = useState(false);
  const [crmPeriodicSyncEnabled, setCrmPeriodicSyncEnabled] = useState(false);
  const [crmWritesEnabled, setCrmWritesEnabled] = useState(false);
  const [crmFieldMappings, setCrmFieldMappings] = useState<FieldMapping[]>([]);
  // Deal sync filter state - filter deals based on a CRM field value
  const [crmDealSyncFilter, setCrmDealSyncFilter] = useState<Record<string, string>>({});
  // Stage required fields state - maps stage values to required CRM field names
  const [stageRequiredFields, setStageRequiredFields] = useState<Record<string, string[]>>({});
  // Custom object config state (Salesforce only)
  const [customObjectName, setCustomObjectName] = useState('');
  const [customObjectFilterField, setCustomObjectFilterField] = useState('');
  const [customObjectFieldsInput, setCustomObjectFieldsInput] = useState('');
  const [customObjectLimit, setCustomObjectLimit] = useState('');

  // Derive connection type and fields from capabilities (loaded from server)
  const connectionType = capabilities?.connectionType;
  const connectionFields = useMemo(
    () => capabilities?.connectionFields || [],
    [capabilities?.connectionFields],
  );
  const apiKeyInstructions = capabilities?.apiKeyInstructions;
  const webhookScope = capabilities?.webhookScope;
  const webhookSetupInstructions = capabilities?.webhookSetupInstructions;
  const hasCreateWebhook = capabilities?.hasCreateWebhook;
  const webhookUrl = `https://api.mail.cedarcopilot.com/webhooks/meeting-notes/${providerId}`;

  // CRM-specific capabilities
  const isCrmProvider = integrationType === 'crm';
  const hasUpdateOpportunityFields = capabilities?.hasUpdateOpportunityFields;
  const defaultWriteFieldMappings = useMemo(
    () => capabilities?.defaultWriteFieldMappings || [],
    [capabilities?.defaultWriteFieldMappings],
  );

  // Get available Cedar fields (core + custom from org AOPs + common values)
  const availableCedarFields = useMemo(() => {
    // Narrow the opaque customFieldDefinitions values to the label shape the util reads.
    const aops = orgDefaultAopConfigs as Array<{
      customFieldDefinitions?: Record<string, { label?: string }> | null;
    }> | undefined;
    return getAvailableCedarFields(aops);
  }, [orgDefaultAopConfigs]);

  // Copy webhook URL to clipboard
  const handleCopyWebhookUrl = async () => {
    try {
      await navigator.clipboard.writeText(webhookUrl);
      setCopiedWebhookUrl(true);
      setTimeout(() => setCopiedWebhookUrl(false), 2000);
    } catch {
      toast.error('Failed to copy to clipboard');
    }
  };

  // Field mapping handlers
  const handleAddMapping = (selectedCrmField?: string) => {
    if (!selectedCrmField) return;
    const mappedCrmFields = new Set(crmFieldMappings.map((m) => m.crmFieldName));
    if (mappedCrmFields.has(selectedCrmField)) {
      toast.error(`Field "${selectedCrmField}" already has a mapping`);
      return;
    }
    // Auto-populate allowedValues if this field has picklist values
    const picklistValues = extractPicklistValues(
      crmPropertiesData?.picklist_fields?.[selectedCrmField],
    );
    setCrmFieldMappings((prev) => [
      ...prev,
      {
        crmFieldName: selectedCrmField,
        cedarFieldName: '',
        allowedValues: picklistValues,
      },
    ]);
  };

  const handleRemoveMapping = (crmFieldName: string) => {
    setCrmFieldMappings((prev) => prev.filter((m) => m.crmFieldName !== crmFieldName));
  };

  const handleSimpleMappingChange = (
    crmFieldName: string,
    cedarFieldName: string,
    allowedValues?: string[],
  ) => {
    setCrmFieldMappings((prev) => {
      const existing = prev.find((m) => m.crmFieldName === crmFieldName);
      if (existing) {
        const currentAllowedValues =
          isSimpleMapping(existing) || isComplexMapping(existing)
            ? existing.allowedValues
            : undefined;
        return prev.map((m) =>
          m.crmFieldName === crmFieldName
            ? { crmFieldName, cedarFieldName, allowedValues: allowedValues ?? currentAllowedValues }
            : m,
        );
      }
      return [...prev, { crmFieldName, cedarFieldName, allowedValues }];
    });
  };

  const handleComplexMappingChange = (
    crmFieldName: string,
    template: string,
    transformations?: Record<string, { type: 'date' | 'number' | 'string'; format?: string }>,
    allowedValues?: string[],
    prefix?: string,
  ) => {
    setCrmFieldMappings((prev) => {
      const existing = prev.find((m) => m.crmFieldName === crmFieldName);
      if (existing) {
        const currentAllowedValues =
          isSimpleMapping(existing) || isComplexMapping(existing)
            ? existing.allowedValues
            : undefined;
        const currentPrefix = isComplexMapping(existing) ? existing.prefix : undefined;
        const currentTransformations = isComplexMapping(existing)
          ? existing.transformations
          : undefined;
        return prev.map((m) =>
          m.crmFieldName === crmFieldName
            ? {
                crmFieldName,
                template,
                prefix: prefix !== undefined ? prefix : currentPrefix,
                transformations:
                  transformations !== undefined ? transformations : currentTransformations,
                allowedValues: allowedValues ?? currentAllowedValues,
              }
            : m,
        );
      }
      return [...prev, { crmFieldName, template, prefix, transformations, allowedValues }];
    });
  };

  const handleToggleMappingType = (crmFieldName: string, isSimple: boolean) => {
    setCrmFieldMappings((prev) => {
      return prev.map((m) => {
        if (m.crmFieldName !== crmFieldName) return m;
        const allowedValues =
          isSimpleMapping(m) || isComplexMapping(m) ? m.allowedValues : undefined;
        if (isSimple) {
          // Convert complex to simple
          if (isComplexMapping(m)) {
            const placeholders = m.template.match(/\{([^}]+)\}/g);
            const firstField = placeholders?.[0]?.replace(/[{}]/g, '') || '';
            return {
              crmFieldName,
              cedarFieldName: firstField,
              allowedValues,
            };
          }
          return m;
        } else {
          // Convert simple to complex
          if (isSimpleMapping(m)) {
            return {
              crmFieldName,
              template: m.cedarFieldName ? `{${m.cedarFieldName}}` : '',
              transformations: {},
              allowedValues,
            };
          }
          return m;
        }
      });
    });
  };

  const handleCrmFieldNameChange = (oldCrmFieldName: string, newCrmFieldName: string) => {
    const mappedCrmFields = new Set(crmFieldMappings.map((m) => m.crmFieldName));
    if (mappedCrmFields.has(newCrmFieldName) && newCrmFieldName !== oldCrmFieldName) {
      toast.error(`Field "${newCrmFieldName}" already has a mapping`);
      return;
    }
    // Auto-populate allowedValues if the new field has picklist values
    const newAllowedValues = extractPicklistValues(
      crmPropertiesData?.picklist_fields?.[newCrmFieldName],
    );
    setCrmFieldMappings((prev) => {
      return prev.map((m) => {
        if (m.crmFieldName !== oldCrmFieldName) return m;
        if (isSimpleMapping(m)) {
          return { ...m, crmFieldName: newCrmFieldName, allowedValues: newAllowedValues };
        } else if (isComplexMapping(m)) {
          return { ...m, crmFieldName: newCrmFieldName, allowedValues: newAllowedValues };
        }
        return m;
      });
    });
  };

  const handleAllowedValuesChange = (crmFieldName: string, allowedValues: string[]) => {
    setCrmFieldMappings((prev) => {
      return prev.map((m) => {
        if (m.crmFieldName !== crmFieldName) return m;
        if (isSimpleMapping(m)) {
          return { ...m, allowedValues: allowedValues.length > 0 ? allowedValues : undefined };
        } else if (isComplexMapping(m)) {
          return { ...m, allowedValues: allowedValues.length > 0 ? allowedValues : undefined };
        }
        return m;
      });
    });
  };

  // Intelligent default for userMustAuthenticate based on connection type
  const defaultUserMustAuth = useMemo(() => {
    const connType = connectionType || orgConfig?.type;
    if (connType === 'oauth') return true;
    if (connType === 'manual') return true;
    return false; // api_key providers default to auto-provision
  }, [connectionType, orgConfig?.type]);

  // Initialize form state when dialog opens or orgConfig changes
  useEffect(() => {
    if (isDialogOpen && mode === 'admin') {
      // Initialize form fields (empty - we don't show existing credentials)
      const initialFields: Record<string, string> = {};
      connectionFields.forEach((field) => {
        initialFields[field.key] = '';
      });
      setFormFields(initialFields);

      // Initialize CRM settings from orgConfig or driver defaults
      if (isCrmProvider) {
        setCrmPeriodicSyncEnabled(orgConfig?.defaultPeriodicDealSyncEnabled ?? false);
        setCrmWritesEnabled(orgConfig?.defaultExternalCrmPushEnabled ?? false);
        const rawMappings = orgConfig?.defaultFieldMappings ?? defaultWriteFieldMappings;
        const mappings = normalizeFieldMappings(rawMappings as Array<unknown>);
        setCrmFieldMappings(mappings);
  // Initialize deal sync filter from orgConfig
  const savedFilter = orgConfig?.defaultDealSyncFilter;
  if (savedFilter && typeof savedFilter === 'object') {
    setCrmDealSyncFilter(savedFilter);
  } else {
    setCrmDealSyncFilter({});
  }
  // Initialize custom object config from orgConfig
  const savedCustomObject = orgConfig?.defaultCustomObjectConfig;
  setCustomObjectName(savedCustomObject?.object_name ?? '');
  setCustomObjectFilterField(savedCustomObject?.filter_field ?? '');
  setCustomObjectFieldsInput((savedCustomObject?.fields ?? []).join(', '));
  setCustomObjectLimit(savedCustomObject?.limit ? String(savedCustomObject.limit) : '');
      }
    }
  }, [
    isDialogOpen,
    mode,
    orgConfig,
    connectionFields,
    isCrmProvider,
    defaultWriteFieldMappings,
  ]);


  // Admin mutations (regular org admin)
  const { mutateAsync: setProviderConfig } = useMutation(
    trpc.orgAdmin.setProviderConfig.mutationOptions(),
  );

  const { mutateAsync: deleteProviderConfig } = useMutation(
    trpc.orgAdmin.deleteProviderConfig.mutationOptions(),
  );

  // Super admin mutations (for Cedar admins managing any org)
  const { mutateAsync: superAdminSetProviderConfig } = useMutation(
    trpc.cedarAdmin.setOrgProviderConfig.mutationOptions(),
  );

  const { mutateAsync: superAdminDeleteProviderConfig } = useMutation(
    trpc.cedarAdmin.deleteOrgProviderConfig.mutationOptions(),
  );

  // OAuth mutations (for admin install flow)
  const { mutateAsync: initiateOAuth } = useMutation(
    trpc.integrations.initiateOAuth.mutationOptions(),
  );

  const { mutateAsync: connect } = useMutation(trpc.integrations.connect.mutationOptions());

  // Webhook status query (only for meeting integrations that support programmatic webhook creation)
  const {
    data: webhookStatus,
    refetch: refetchWebhookStatus,
  } = useQuery({
    ...trpc.integrations.meetings.getWebhookStatus.queryOptions({
      providerId,
    }),
    // Only enable for meeting integrations with org-level webhooks and programmatic creation support
    enabled: mode === 'admin' && webhookScope === 'org' && hasCreateWebhook === true && isDialogOpen,
  });

  // CRM properties query (for field mappings)
  // In admin mode, use the admin's connection (created when they OAuth install)
  const adminUserId = orgConfig?.adminUserId;
  const { data: crmPropertiesData, isFetching: isFetchingCrmProperties } = useQuery({
    ...trpc.integrations.crm.getProperties.queryOptions({
      providerId: providerId as 'hubspot' | 'attio' | 'salesforce' | 'copper',
      // In admin mode, pass the adminUserId to fetch properties using their connection
      userId: mode === 'admin' && adminUserId ? adminUserId : undefined,
    }),
    // Enable when:
    // - It's a CRM provider with field mapping support
    // - Dialog is open
    // - In admin mode: require adminUserId (connection must exist)
    // - In user mode: always enable
    enabled:
      isCrmProvider &&
      hasUpdateOpportunityFields === true &&
      isDialogOpen &&
      (mode !== 'admin' || !!adminUserId),
  });

  // Admin connection query — resolve admin's connectionId for updateWriteSettings
  const { data: adminIntegrationsData } = useQuery({
    ...trpc.integrations.list.queryOptions(adminUserId ? { userId: adminUserId } : undefined),
    enabled: mode === 'admin' && isCrmProvider && hasUpdateOpportunityFields === true && !!adminUserId && isDialogOpen,
  });
  const adminConnectionId = useMemo(() => {
    const integration = adminIntegrationsData?.integrations.find(
      (i) => i.id === providerId && (i as { connected?: boolean }).connected,
    );
    return (integration as { connectionId?: string } | undefined)?.connectionId;
  }, [adminIntegrationsData, providerId]);

  const { data: adminConnectionData } = useQuery({
    ...trpc.connections.get.queryOptions({ connectionId: adminConnectionId!, userId: adminUserId }),
    enabled: !!adminConnectionId && !!adminUserId && isDialogOpen,
  });

  const { mutateAsync: updateWriteSettings } = useMutation(
    trpc.integrations.crm.updateWriteSettings.mutationOptions(),
  );

  // Initialize stageRequiredFields from admin connection metadata (fallback to Superglue data)
  useEffect(() => {
    if (!isDialogOpen || !isCrmProvider) return;
    const meta = (adminConnectionData?.metadata as Record<string, unknown> | undefined) ?? {};
    const saved = meta.stageRequiredFields as Record<string, string[]> | undefined;
    if (saved && Object.keys(saved).length > 0) {
      setStageRequiredFields(saved);
    } else if (crmPropertiesData?.stage_required_fields && Object.keys(crmPropertiesData.stage_required_fields).length > 0) {
      setStageRequiredFields(crmPropertiesData.stage_required_fields);
    } else {
      setStageRequiredFields({});
    }
  }, [isDialogOpen, isCrmProvider, adminConnectionData, crmPropertiesData?.stage_required_fields]);

  // Create webhook mutation
  const { mutateAsync: createWebhook } = useMutation({
    ...trpc.integrations.meetings.createWebhook.mutationOptions(),
    onSuccess: (data) => {
      if (data.success) {
        refetchWebhookStatus();
      } else {
        toast.error(data.error || 'Failed to create webhook');
      }
      setIsCreatingWebhook(false);
    },
    onError: (error) => {
      toast.error(error.message || 'Failed to create webhook');
      setIsCreatingWebhook(false);
    },
  });

  const handleCreateWebhook = async () => {
    setIsCreatingWebhook(true);
    await createWebhook({ providerId });
  };

  // Status checks - OAuth providers use isInstalled, API key providers use hasCredentials, manual use isEnabled
  // When connectionType is undefined (capabilities not loaded), check orgConfig.type as fallback
  const effectiveConnectionType = connectionType || orgConfig?.type;
  const isConfigured =
    mode === 'admin'
      ? effectiveConnectionType === 'oauth'
        ? orgConfig?.isInstalled
        : effectiveConnectionType === 'manual'
          ? orgConfig?.isEnabled
          : orgConfig?.hasCredentials
      : isConnected;

  // Handle OAuth install for admin mode (follows same pattern as CrmIntegrationCard)
  const handleOAuthInstall = async () => {
    if (mode !== 'admin') return;

    try {
      setIsInstalling(true);

      // Step 1: Get OAuth URL (same as user flow)
      const { oauthUrl, strataServerUrl } = await initiateOAuth({
        integration: providerId,
      });

      if (!oauthUrl) {
        setIsInstalling(false);
        toast.error('Failed to get OAuth URL');
        return;
      }

      // Step 2: Store strataServerUrl for verification (same pattern as user flow)
      sessionStorage.setItem(
        `${providerId}_oauth_admin_pending`,
        JSON.stringify({ strataServerUrl }),
      );

      // Step 3: Open OAuth in new tab
      window.open(oauthUrl, '_blank');
    } catch (error) {
      console.error(`[ProviderConfigCard] Error initiating OAuth for ${providerId}:`, error);
      toast.error(
        `Failed to initiate OAuth: ${error instanceof Error ? error.message : String(error)}`,
      );
      setIsInstalling(false);
    }
  };

  // Window focus listener - follows same pattern as CrmIntegrationCard
  useEffect(() => {
    const handleWindowFocus = async () => {
      const storageKey=[redacted];
      const pendingAuth = sessionStorage.getItem(storageKey);

      if (pendingAuth && isInstalling) {
        console.log(
          `[ProviderConfigCard] Admin returned from OAuth tab for ${providerId}, checking connection...`,
        );

        try {
          const { strataServerUrl } = JSON.parse(pendingAuth);

          // Step 4: Verify OAuth succeeded by calling connect
          // Mark as admin install so this connection is NOT treated as a user connection
          // The admin will need to go through user onboarding to create their own user connection
          await connect({
            providerId: providerId as ProviderId,
            connectionParams: { strataServerUrl },
            isAdminInstall: true,
          });

          // Step 5: After verification, mark provider as installed at org level
          await setProviderConfig({
            providerId,
            config: {
              type: 'oauth',
              isInstalled: true,
              adminUserId: session?.user?.id,
              installedAt: new Date().toISOString(),
              userMustAuthenticate: true,
            },
          });

          sessionStorage.removeItem(storageKey);
          setIsInstalling(false);
          setIsDialogOpen(false);

          // Invalidate queries to refresh org config (which includes adminUserId)
          queryClient.invalidateQueries({ queryKey=[redacted] });
          
          // Also invalidate CRM properties query so it refetches with the new adminUserId
          if (isCrmProvider && hasUpdateOpportunityFields && session?.user?.id) {
            queryClient.invalidateQueries({
              queryKey: [
                ['integrations', 'crm', 'getProperties'],
                {
                  providerId: providerId as 'hubspot' | 'attio' | 'salesforce' | 'copper',
                  userId: session.user.id,
                },
              ],
            });
          }

          onConfigured?.();
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : String(error);
          // Ignore expected auth-in-progress errors (user may not have completed OAuth yet)
          const isExpectedError =
            errorMessage.includes('not authenticated') ||
            errorMessage.includes('Unauthorized') ||
            errorMessage.includes('Please complete OAuth flow');

          if (!isExpectedError) {
            console.error(`[ProviderConfigCard] Error installing ${providerId}:`, error);
            sessionStorage.removeItem(storageKey);
            setIsInstalling(false);
            toast.error(`Failed to install ${integrationInfo.name}: ${errorMessage}`);
          }
        }
      }
    };

    window.addEventListener('focus', handleWindowFocus);
    return () => window.removeEventListener('focus', handleWindowFocus);
  }, [
    isInstalling,
    providerId,
    session?.user?.id,
    connect,
    setProviderConfig,
    onConfigured,
    integrationInfo.name,
    isCrmProvider,
    hasUpdateOpportunityFields,
    queryClient,
    trpc.orgAdmin.getProviderConfigs,
  ]);

  // Handle save for admin mode
  const handleSaveConfig = async () => {
    if (mode !== 'admin') return;

    // For API key providers, validate required fields
    if (effectiveConnectionType === 'api_key') {
      const missingFields = connectionFields.filter(
        (field) => field.type === 'password' && !formFields[field.key]?.trim(),
      );
      // Only require fields if this is a new config (not updating)
      if (!isConfigured && missingFields.length > 0) {
        toast.error(
          `Please fill in required fields: ${missingFields.map((f) => f.label).join(', ')}`,
        );
        return;
      }
    }

    try {
      setIsSaving(true);

      // Build credentials object from form fields (only non-empty values)
      const credentials: Record<string, string> = {};
      for (const [key, value] of Object.entries(formFields)) {
        if (value.trim()) {
          credentials[key] = value.trim();
        }
      }

      // Build CRM settings if applicable
const customObjectFields = customObjectFieldsInput
  .split(',')
  .map((f) => f.trim())
  .filter(Boolean);
const customObjectLimitParsed = customObjectLimit ? parseInt(customObjectLimit, 10) : undefined;
const customObjectConfig =
  customObjectName.trim() && customObjectFilterField.trim()
    ? {
        object_name: customObjectName.trim(),
        filter_field: customObjectFilterField.trim(),
        fields: customObjectFields.length > 0 ? customObjectFields : undefined,
        limit: customObjectLimitParsed && !isNaN(customObjectLimitParsed) ? customObjectLimitParsed : undefined,
      }
    : undefined;

const crmSettings = isCrmProvider
  ? {
      defaultFieldMappings: crmFieldMappings.length > 0 ? crmFieldMappings : undefined,
      defaultPeriodicDealSyncEnabled: crmPeriodicSyncEnabled,
      defaultExternalCrmPushEnabled: crmWritesEnabled,
      defaultDealSyncFilter:
        Object.keys(crmDealSyncFilter).length > 0 ? crmDealSyncFilter : undefined,
      defaultCustomObjectConfig: customObjectConfig,
    }
  : {};

      const configPayload = {
        type: (effectiveConnectionType || 'api_key') as 'api_key' | 'oauth' | 'service_account' | 'manual',
        credentials: Object.keys(credentials).length > 0 ? credentials : undefined,
        userMustAuthenticate: defaultUserMustAuth,
        ...crmSettings,
      };

      // Use super admin mutation if managing another org
      if (superAdminOrgId) {
        await superAdminSetProviderConfig({
          organizationId: superAdminOrgId,
          providerId,
          config: configPayload,
        });
        queryClient.invalidateQueries({
          queryKey=[redacted] organizationId: superAdminOrgId }),
        });
      } else {
        await setProviderConfig({
          providerId,
          config: configPayload,
        });
        queryClient.invalidateQueries({ queryKey=[redacted] });
      }

      // Also persist stageRequiredFields to admin's connection metadata
      if (isCrmProvider && adminConnectionId && Object.keys(stageRequiredFields).length > 0) {
        await updateWriteSettings({
          connectionId: adminConnectionId,
          stageRequiredFields: Object.keys(stageRequiredFields).length > 0 ? stageRequiredFields : undefined,
          userId: adminUserId,
        });
        queryClient.invalidateQueries({ queryKey=[redacted] connectionId: adminConnectionId, userId: adminUserId }) });
      }

      setIsDialogOpen(false);
      setFormFields({});

      onConfigured?.();
    } catch (error) {
      console.error('[ProviderConfigCard] Error saving config:', error);
      toast.error(
        `Failed to save configuration: ${error instanceof Error ? error.message : String(error)}`,
      );
    } finally {
      setIsSaving(false);
    }
  };


  // Handle remove for admin mode
  const handleRemoveConfig = async () => {
    if (mode !== 'admin') return;

    try {
      setIsRemoving(true);

      // Use super admin mutation if managing another org
      if (superAdminOrgId) {
        await superAdminDeleteProviderConfig({
          organizationId: superAdminOrgId,
          providerId,
        });
        queryClient.invalidateQueries({
          queryKey=[redacted] organizationId: superAdminOrgId }),
        });
      } else {
        await deleteProviderConfig({ providerId });
        queryClient.invalidateQueries({ queryKey=[redacted] });
      }

      setIsDialogOpen(false);

      onRemoved?.();
    } catch (error) {
      console.error('[ProviderConfigCard] Error removing config:', error);
      toast.error(
        `Failed to remove configuration: ${error instanceof Error ? error.message : String(error)}`,
      );
    } finally {
      setIsRemoving(false);
    }
  };

  // Handle enable/disable for manual connection types
  const [isTogglingEnabled, setIsTogglingEnabled] = useState(false);
  const handleToggleEnabled = async () => {
    if (mode !== 'admin') return;

    try {
      setIsTogglingEnabled(true);
      const newEnabled = !isConfigured;

      if (newEnabled) {
        // Enable the integration
        await setProviderConfig({
          providerId,
          config: {
            type: 'manual' as const,
            isEnabled: true,
          },
        });
        onConfigured?.();
      } else {
        // Disable the integration
        await deleteProviderConfig({ providerId });
        onRemoved?.();
      }

      // Invalidate queries
      queryClient.invalidateQueries({ queryKey=[redacted] });
    } catch (error) {
      console.error('[ProviderConfigCard] Error toggling enabled:', error);
      toast.error(
        `Failed to ${isConfigured ? 'disable' : 'enable'}: ${error instanceof Error ? error.message : String(error)}`,
      );
    } finally {
      setIsTogglingEnabled(false);
    }
  };

  // Render a form field
  const renderFormField = (field: ConnectionField) => {
    const isPassword=[redacted] === 'password';
    const showPassword=[redacted] || false;

    return (
      <div key=[redacted] className="space-y-2">
        <Label htmlFor={`${providerId}-${field.key}`} className="text-sm font-medium">
          {field.label}
        </Label>
        <div className="relative">
          <Input
            id={`${providerId}-${field.key}`}
            type={isPassword && !showPassword ? 'password' : 'text'}
            placeholder={isConfigured ? '••••••••' : field.placeholder}
            value={formFields[field.key] || ''}
            onChange={(e) => setFormFields((prev) => ({ ...prev, [field.key]: e.target.value }))}
            disabled={isSaving}
            className={isPassword ? 'pr-10' : ''}
          />
          {isPassword && (
            <Button
              type="button"
              variant="ghost"
              size="icon"
              className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
              onClick={() => setShowPasswords((prev) => ({ ...prev, [field.key]: !showPassword }))}
            >
              {showPassword ? (
                <EyeOff className="h-4 w-4 text-muted-foreground" />
              ) : (
                <Eye className="h-4 w-4 text-muted-foreground" />
              )}
            </Button>
          )}
        </div>
        {isConfigured && isPassword && (
          <p className="text-xs text-muted-foreground">Leave blank to keep existing value</p>
        )}
      </div>
    );
  };

  return (
    <div
      className={`relative rounded-lg border p-4 transition-colors ${
        isConfigured
          ? 'border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20'
          : 'hover:bg-muted/50'
      }`}
    >
      {/* Header */}
      <div className="flex items-start gap-3">
        <div
          className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-sm font-bold text-white"
          style={{ backgroundColor: integrationInfo.iconColor }}
        >
          {integrationInfo.iconLetter}
        </div>
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <h4 className="font-medium">{integrationInfo.name}</h4>
            {isConfigured && (
              <Badge
                variant="secondary"
                className="bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300"
              >
                <Check className="mr-1 h-3 w-3" />
                {mode === 'admin'
                  ? effectiveConnectionType === 'oauth'
                    ? 'Installed'
                    : effectiveConnectionType === 'manual'
                      ? 'Enabled'
                      : 'Configured'
                  : 'Connected'}
              </Badge>
            )}
          </div>
          <p className="text-muted-foreground mt-1 text-xs">{integrationInfo.description}</p>
        </div>
      </div>

      {/* Configure/Edit Button or Enable Toggle */}
      {mode === 'admin' && (
        <div className="mt-3 flex gap-2">
          {/* Manual connection types with user-level webhooks - simple enable toggle */}
          {effectiveConnectionType === 'manual' && webhookScope !== 'org' ? (
            <Button
              variant={isConfigured ? 'secondary' : brandColor ? 'default' : 'outline'}
              size="sm"
              className="flex-1"
              style={brandColor && !isConfigured ? { 
                backgroundColor: brandColor, 
                borderColor: brandColor,
                color: getContrastTextColor(brandColor),
              } : undefined}
              onClick={handleToggleEnabled}
              disabled={isTogglingEnabled}
            >
              {isTogglingEnabled ? (
                <>
                  <Loader2 className="mr-2 h-3 w-3 animate-spin" />
                  {isConfigured ? 'Disabling...' : 'Enabling...'}
                </>
              ) : isConfigured ? (
                <>
                  <Check className="mr-2 h-3 w-3" />
                  Enabled
                </>
              ) : (
                'Enable'
              )}
            </Button>
          ) : useFullPageConfig ? (
            /* Full page configuration - navigate to integration config page */
            <Button
              variant={brandColor ? 'default' : 'outline'}
              size="sm"
              className="flex-1"
              style={brandColor ? { 
                backgroundColor: brandColor, 
                borderColor: brandColor,
                color: getContrastTextColor(brandColor),
              } : undefined}
              onClick={() => navigate(`/admin/integration?provider=${providerId}`)}
            >
              {isConfigured ? (
                <>
                  <Settings className="mr-2 h-3 w-3" />
                  {effectiveConnectionType === 'oauth' ? 'Manage' : effectiveConnectionType === 'manual' ? 'Manage' : 'Edit Configuration'}
                </>
              ) : (
                <>
                  <ExternalLink className="mr-2 h-3 w-3" />
                  Configure
                </>
              )}
            </Button>
          ) : (
            /* API Key, OAuth, or Manual with org-level webhooks - dialog configuration */
            <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
              <DialogTrigger asChild>
                <Button
                  variant={brandColor ? 'default' : 'outline'}
                  size="sm"
                  className="flex-1"
                  style={brandColor ? { 
                    backgroundColor: brandColor, 
                    borderColor: brandColor,
                    color: getContrastTextColor(brandColor),
                  } : undefined}
                >
                  {isConfigured ? (
                    <>
                      <Settings className="mr-2 h-3 w-3" />
                      {effectiveConnectionType === 'oauth' ? 'Manage' : effectiveConnectionType === 'manual' ? 'Manage' : 'Edit Configuration'}
                    </>
                  ) : (
                    <>
                      <ExternalLink className="mr-2 h-3 w-3" />
                      Configure
                    </>
                  )}
                </Button>
              </DialogTrigger>
            <DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-xl">
              <DialogHeader>
                <DialogTitle className="flex items-center gap-2">
                  <div
                    className="flex h-6 w-6 shrink-0 items-center justify-center rounded text-xs font-bold text-white"
                    style={{ backgroundColor: integrationInfo.iconColor }}
                  >
                    {integrationInfo.iconLetter}
                  </div>
                  Configure {integrationInfo.name}
                </DialogTitle>
                <DialogDescription>
                  {effectiveConnectionType === 'oauth'
                    ? `Install ${integrationInfo.name} to make it available for your team during onboarding.`
                    : effectiveConnectionType === 'manual'
                      ? `Enable ${integrationInfo.name} and configure the webhook for your organization.`
                      : `Enter your ${integrationInfo.name} API credentials to enable this integration.`}
                </DialogDescription>
              </DialogHeader>

              <div className="space-y-4 py-4">
                {/* API Key Instructions */}
                {effectiveConnectionType === 'api_key' && apiKeyInstructions && (
                  <Collapsible open={showInstructions} onOpenChange={setShowInstructions}>
                    <CollapsibleTrigger asChild>
                      <Button variant="ghost" size="sm" className="w-full justify-between">
                        <span className="text-sm">How to get your API key</span>
                        {showInstructions ? (
                          <ChevronUp className="h-4 w-4" />
                        ) : (
                          <ChevronDown className="h-4 w-4" />
                        )}
                      </Button>
                    </CollapsibleTrigger>
                    <CollapsibleContent>
                      <div className="mt-2 rounded-lg border bg-muted/30 p-3">
                        <pre className="whitespace-pre-wrap font-sans text-xs text-muted-foreground">
                          {apiKeyInstructions}
                        </pre>
                      </div>
                    </CollapsibleContent>
                  </Collapsible>
                )}

                {/* Form Fields for API Key providers */}
                {effectiveConnectionType === 'api_key' && connectionFields.length > 0 && (
                  <div className="space-y-3">{connectionFields.map(renderFormField)}</div>
                )}

                {/* OAuth providers - Install flow */}
                {effectiveConnectionType === 'oauth' && (
                  <div className="space-y-4">
                    {isConfigured ? (
                      <div className="rounded-lg border border-green-200 bg-green-50 p-4 dark:border-green-800 dark:bg-green-950/30">
                        <div className="flex items-center gap-2">
                          <CheckCircle className="h-5 w-5 text-green-600 dark:text-green-400" />
                          <p className="font-medium text-green-700 dark:text-green-300">
                            Installed
                          </p>
                        </div>
                        <p className="mt-1 text-sm text-green-600 dark:text-green-400">
                          {orgConfig?.installedAt
                            ? `Installed on ${new Date(orgConfig.installedAt).toLocaleDateString()}`
                            : 'This integration is available for your team.'}
                        </p>
                        <p className="mt-2 text-xs text-muted-foreground">
                          Team members will be prompted to connect their own {integrationInfo.name}{' '}
                          accounts during onboarding.
                        </p>
                      </div>
                    ) : (
                      <div className="rounded-lg border bg-muted/30 p-4">
                        <p className="mb-4 text-sm text-muted-foreground">
                          You must install this integration before team members can connect. Click
                          below to authenticate with {integrationInfo.name} and approve the app for
                          your organization.
                        </p>
                        <Button
                          onClick={handleOAuthInstall}
                          disabled={isInstalling}
                          className="w-full"
                        >
                          {isInstalling ? (
                            <>
                              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                              Installing...
                            </>
                          ) : (
                            <>
                              <ExternalLink className="mr-2 h-4 w-4" />
                              Install {integrationInfo.name}
                            </>
                          )}
                        </Button>
                      </div>
                    )}
                  </div>
                )}

                {/* Webhook Configuration Info (for meeting integrations) */}
                {webhookScope && webhookScope !== 'none' && (
                  <div className="rounded-lg border bg-muted/30 p-3">
                    <Label className="text-sm font-medium">Webhook Configuration</Label>
                    {webhookScope === 'org' ? (
                      <div className="mt-2 space-y-3">
                        <p className="text-xs text-muted-foreground">
                          Webhook setup is done once at the organization level.
                        </p>

                        {/* Programmatic webhook creation (e.g., Fathom) */}
                        {hasCreateWebhook ? (
                          <div className="space-y-3">
                            {webhookStatus?.hasWebhook ? (
                              <div className="rounded-lg border border-green-200 bg-green-50 p-3 dark:border-green-800 dark:bg-green-950/30">
                                <div className="flex items-center gap-2">
                                  <CheckCircle className="h-4 w-4 text-green-600 dark:text-green-400" />
                                  <p className="text-sm font-medium text-green-700 dark:text-green-300">
                                    Webhook configured
                                  </p>
                                </div>
                                {webhookStatus?.webhookUrl && (
                                  <p className="mt-1 font-mono text-xs text-green-600 dark:text-green-400">
                                    {webhookStatus.webhookUrl}
                                  </p>
                                )}
                              </div>
                            ) : (
                              <div className="space-y-2">
                                <p className="text-xs text-muted-foreground">
                                  Click the button below to automatically create the webhook.
                                </p>
                                <Button
                                  onClick={handleCreateWebhook}
                                  disabled={isCreatingWebhook || !isConfigured}
                                  className="w-full"
                                  size="sm"
                                >
                                  {isCreatingWebhook ? (
                                    <>
                                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                      Creating Webhook...
                                    </>
                                  ) : (
                                    'Create Webhook'
                                  )}
                                </Button>
                                {!isConfigured && (
                                  <p className="text-xs text-amber-600 dark:text-amber-400">
                                    Save credentials first before creating the webhook.
                                  </p>
                                )}
                              </div>
                            )}
                          </div>
                        ) : (
                          <>
                            {/* Manual webhook setup - show URL and instructions */}
                            <div className="space-y-1">
                              <Label className="text-xs text-muted-foreground">Webhook URL</Label>
                              <div className="flex items-center gap-2">
                                <Input
                                  readOnly
                                  value={webhookUrl}
                                  className="font-mono text-xs"
                                />
                                <Button
                                  variant="outline"
                                  size="icon"
                                  className="shrink-0"
                                  onClick={handleCopyWebhookUrl}
                                >
                                  {copiedWebhookUrl ? (
                                    <Check className="h-4 w-4 text-green-600" />
                                  ) : (
                                    <Copy className="h-4 w-4" />
                                  )}
                                </Button>
                              </div>
                            </div>

                            {webhookSetupInstructions && (
                              <Collapsible>
                                <CollapsibleTrigger asChild>
                                  <Button variant="ghost" size="sm" className="w-full justify-between">
                                    <span className="text-sm">Setup instructions</span>
                                    <ChevronDown className="h-4 w-4" />
                                  </Button>
                                </CollapsibleTrigger>
                                <CollapsibleContent>
                                  <div className="mt-2 rounded-lg border bg-background p-3">
                                    <pre className="whitespace-pre-wrap font-sans text-xs text-muted-foreground">
                                      {webhookSetupInstructions}
                                    </pre>
                                  </div>
                                </CollapsibleContent>
                              </Collapsible>
                            )}
                          </>
                        )}
                      </div>
                    ) : (
                      <p className="mt-2 text-xs text-muted-foreground">
                        Each user will need to configure their own webhook during onboarding.
                      </p>
                    )}
                  </div>
                )}

                {/* CRM Settings (for CRM integrations) */}
                {isCrmProvider && hasUpdateOpportunityFields && (
                  <div className="space-y-3 rounded-lg border bg-muted/30 p-3">
                    <div className="flex items-center justify-between">
                      <Label className="text-sm font-medium">CRM Default Settings</Label>
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={() => setShowCrmSettings(!showCrmSettings)}
                      >
                        {showCrmSettings ? (
                          <>
                            <ChevronUp className="mr-1 h-4 w-4" />
                            Hide
                          </>
                        ) : (
                          <>
                            <ChevronDown className="mr-1 h-4 w-4" />
                            Configure
                          </>
                        )}
                      </Button>
                    </div>
                    <p className="text-xs text-muted-foreground">
                      Set default sync and write settings for your team. Users can customize these.
                    </p>

                    {showCrmSettings && (
                      <div className="space-y-4 pt-2">
                        {/* Sync and Write toggles */}
                        <div className="space-y-3">
                          <div className="flex items-center space-x-2">
                            <Checkbox
                              id={`${providerId}-default-periodic-sync`}
                              checked={crmPeriodicSyncEnabled}
                              onCheckedChange={(checked) =>
                                setCrmPeriodicSyncEnabled(checked === true)
                              }
                            />
                            <Label
                              htmlFor={`${providerId}-default-periodic-sync`}
                              className="cursor-pointer text-sm font-normal"
                            >
                              Enable periodic deal sync by default
                              <div className="mt-1 text-xs text-muted-foreground">
                                Automatically sync deals from {integrationInfo.name} on a schedule
                              </div>
                            </Label>
                          </div>
                          <div className="flex items-center space-x-2">
                            <Checkbox
                              id={`${providerId}-default-crm-writes`}
                              checked={crmWritesEnabled}
                              onCheckedChange={(checked) => setCrmWritesEnabled(checked === true)}
                            />
                            <Label
                              htmlFor={`${providerId}-default-crm-writes`}
                              className="cursor-pointer text-sm font-normal"
                            >
                              Enable CRM writes by default
                              <div className="mt-1 text-xs text-muted-foreground">
                                Allow writing updates back to {integrationInfo.name}
                              </div>
                            </Label>
                          </div>
                        </div>

                        {/* Deal Sync Filter */}
                        <div className="space-y-3 border-t pt-3">
                          <Label className="text-xs font-medium">Default Deal Sync Filter</Label>
                          <p className="text-xs text-muted-foreground">
                            Only sync deals matching specific criteria. Users can customize this
                            filter in their settings.
                          </p>
                          {Object.keys(crmDealSyncFilter).length > 0 ? (
                            <div className="space-y-2">
                              {Object.entries(crmDealSyncFilter).map(([fieldName, fieldValue]) => {
                                const picklistValues = crmPropertiesData?.picklist_fields?.[fieldName];
                                const options = extractPicklistOptions(picklistValues);
                                return (
                                  <div
                                    key=[redacted]
                                    className="flex items-center gap-2 rounded-lg border bg-background p-2"
                                  >
                                    <div className="flex-1">
                                      <Popover>
                                        <PopoverTrigger asChild>
                                          <Button
                                            variant="outline"
                                            role="combobox"
                                            className="h-7 w-full justify-between text-xs"
                                          >
                                            <span className="font-mono">{fieldName}</span>
                                            <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                                          </Button>
                                        </PopoverTrigger>
                                        <PopoverContent className="w-[250px] p-0">
                                          <Command>
                                            <CommandInput placeholder="Search fields..." />
                                            <CommandList>
                                              <CommandEmpty>No field found.</CommandEmpty>
                                              <CommandGroup>
                                                {crmPropertiesData?.field_names
                                                  ?.filter((f) => !!crmPropertiesData.picklist_fields?.[f])
                                                  .map((field) => {
                                                    const isSelected = fieldName === field;
                                                    return (
                                                      <CommandItem
                                                        key=[redacted]
                                                        value={field}
                                                        onSelect={() => {
                                                          // Update the filter with new field, clear the value
                                                          const newFilter = { ...crmDealSyncFilter };
                                                          delete newFilter[fieldName];
                                                          newFilter[field] = '';
                                                          setCrmDealSyncFilter(newFilter);
                                                        }}
                                                      >
                                                        <Check
                                                          className={`mr-2 h-4 w-4 ${
                                                            isSelected ? 'opacity-100' : 'opacity-0'
                                                          }`}
                                                        />
                                                        <span className="font-mono text-xs">{field}</span>
                                                        <span className="ml-2 text-xs text-blue-500">
                                                          (picklist)
                                                        </span>
                                                      </CommandItem>
                                                    );
                                                  })}
                                              </CommandGroup>
                                            </CommandList>
                                          </Command>
                                        </PopoverContent>
                                      </Popover>
                                    </div>
                                    <span className="text-muted-foreground text-sm">=</span>
                                    <div className="flex-1">
                                      {options && options.length > 0 ? (
                                        <Select
                                          value={fieldValue}
                                          onValueChange={(value) => {
                                            setCrmDealSyncFilter((prev) => ({
                                              ...prev,
                                              [fieldName]: value,
                                            }));
                                          }}
                                        >
                                          <SelectTrigger size="sm" >
                                            <SelectValue placeholder="Select value..." />
                                          </SelectTrigger>
                                          <SelectContent>
                                            {options.map((option) => (
                                              <SelectItem key=[redacted] value={option.value}>
                                                {option.label}
                                              </SelectItem>
                                            ))}
                                          </SelectContent>
                                        </Select>
                                      ) : (
                                        <Input
                                          value={fieldValue}
                                          onChange={(e) => {
                                            setCrmDealSyncFilter((prev) => ({
                                              ...prev,
                                              [fieldName]: e.target.value,
                                            }));
                                          }}
                                          placeholder="Enter value..."
                                          className="h-7 text-xs"
                                        />
                                      )}
                                    </div>
                                    <Button
                                      variant="ghost"
                                      size="icon"
                                      onClick={() => {
                                        const newFilter = { ...crmDealSyncFilter };
                                        delete newFilter[fieldName];
                                        setCrmDealSyncFilter(newFilter);
                                      }}
                                      className="h-7 w-7"
                                    >
                                      <X className="h-3 w-3" />
                                    </Button>
                                  </div>
                                );
                              })}
                            </div>
                          ) : (
                            <p className="text-center text-xs text-muted-foreground py-2">
                              No filter configured. All deals will be synced.
                            </p>
                          )}
                          {/* Add filter button - only show picklist fields */}
                          {(() => {
                            const picklistFields = crmPropertiesData?.field_names?.filter(
                              (f) =>
                                !!crmPropertiesData.picklist_fields?.[f] &&
                                !Object.keys(crmDealSyncFilter).includes(f),
                            );
                            if (!picklistFields || picklistFields.length === 0) return null;
                            return (
                              <Popover>
                                <PopoverTrigger asChild>
                                  <Button variant="outline" size="sm" className="w-full">
                                    <Plus className="mr-2 h-3 w-3" />
                                    Add Filter
                                  </Button>
                                </PopoverTrigger>
                                <PopoverContent className="w-[250px] p-0">
                                  <Command>
                                    <CommandInput placeholder="Search picklist fields..." />
                                    <CommandList>
                                      <CommandEmpty>No picklist field found.</CommandEmpty>
                                      <CommandGroup>
                                        {picklistFields.map((field) => (
                                          <CommandItem
                                            key=[redacted]
                                            value={field}
                                            onSelect={() => {
                                              setCrmDealSyncFilter((prev) => ({
                                                ...prev,
                                                [field]: '',
                                              }));
                                            }}
                                          >
                                            <span className="font-mono text-xs">{field}</span>
                                            <span className="ml-2 text-xs text-blue-500">(picklist)</span>
                                          </CommandItem>
                                        ))}
                                      </CommandGroup>
                                    </CommandList>
                                  </Command>
                                </PopoverContent>
                              </Popover>
                            );
                          })()}
                        </div>

                        {/* Stage Required Fields */}
                        <div className="space-y-3 border-t pt-3">
                          <Label className="text-xs font-medium">Stage Required Fields</Label>
                          <p className="text-xs text-muted-foreground">
                            Specify which CRM fields are required when moving a deal to each stage.
                          </p>
                          {Object.keys(stageRequiredFields).length > 0 ? (
                            <div className="space-y-2">
                              {Object.entries(stageRequiredFields).map(([stageName, requiredFields]) => (
                                <div
                                  key=[redacted]
                                  className="flex items-start gap-2 rounded-lg border bg-background p-2"
                                >
                                  <div className="min-w-0 flex-1 space-y-1">
                                    <span className="font-mono text-xs font-medium">{stageName}</span>
                                    <div className="flex flex-wrap gap-1">
                                      {requiredFields.map((field) => (
                                        <Badge key=[redacted] variant="secondary" className="font-mono text-xs">
                                          {field}
                                        </Badge>
                                      ))}
                                    </div>
                                    <Input
                                      value={requiredFields.join(', ')}
                                      onChange={(e) => {
                                        const fields = e.target.value
                                          .split(',')
                                          .map((f) => f.trim())
                                          .filter(Boolean);
                                        setStageRequiredFields((prev) => ({
                                          ...prev,
                                          [stageName]: fields,
                                        }));
                                      }}
                                      placeholder="e.g. CloseDate, Amount__c"
                                      className="h-7 text-xs font-mono"
                                    />
                                  </div>
                                  <Button
                                    variant="ghost"
                                    size="icon"
                                    onClick={() => {
                                      const updated = { ...stageRequiredFields };
                                      delete updated[stageName];
                                      setStageRequiredFields(updated);
                                    }}
                                    className="h-7 w-7 shrink-0"
                                  >
                                    <X className="h-3 w-3" />
                                  </Button>
                                </div>
                              ))}
                            </div>
                          ) : (
                            <p className="text-center text-xs text-muted-foreground py-2">
                              No stage requirements configured.
                            </p>
                          )}
                          {/* Add stage requirement */}
                          {(() => {
                            // Suggest stages from Superglue-detected data; user can also type any stage name.
                            const stageOptions = Object.keys(crmPropertiesData?.stage_required_fields ?? {})
                              .filter((s) => !Object.keys(stageRequiredFields).includes(s));
                            return (
                              <Popover>
                                <PopoverTrigger asChild>
                                  <Button variant="outline" size="sm" className="w-full">
                                    <Plus className="mr-2 h-3 w-3" />
                                    Add stage requirement
                                  </Button>
                                </PopoverTrigger>
                                <PopoverContent className="w-[300px] p-0">
                                  <Command>
                                    <CommandInput placeholder="Search or enter stage name..." />
                                    <CommandList>
                                      <CommandEmpty>
                                        <Button
                                          variant="ghost"
                                          size="sm"
                                          className="w-full text-xs"
                                          onClick={() => {
                                            const input = document.querySelector('[cmdk-input]') as HTMLInputElement | null;
                                            const stageName = input?.value?.trim();
                                            if (stageName && !stageRequiredFields[stageName]) {
                                              setStageRequiredFields((prev) => ({
                                                ...prev,
                                                [stageName]: [],
                                              }));
                                            }
                                          }}
                                        >
                                          Add as stage
                                        </Button>
                                      </CommandEmpty>
                                      <CommandGroup>
                                        {stageOptions.map((stage) => (
                                          <CommandItem
                                            key=[redacted]
                                            value={stage}
                                            onSelect={() => {
                                              setStageRequiredFields((prev) => ({
                                                ...prev,
                                                [stage]: [],
                                              }));
                                            }}
                                          >
                                            <span className="font-mono text-xs">{stage}</span>
                                          </CommandItem>
                                        ))}
                                      </CommandGroup>
                                    </CommandList>
                                  </Command>
                                </PopoverContent>
                              </Popover>
                            );
                          })()}
                        </div>

                        {/* Custom Object Config — Salesforce only */}
                        {integrationInfo.id === 'salesforce' && (
                          <div className="space-y-3 border-t pt-3">
                            <Label className="text-xs font-medium">Default Custom Object Sync</Label>
                            <p className="text-xs text-muted-foreground">
                              Salesforce custom object to fetch per deal conversation using the linked
                              Account ID as the filter value. Stamped onto user connections at
                              connect time.
                            </p>
                            <div className="grid grid-cols-2 gap-2">
                              <div className="space-y-1">
                                <Label className="text-xs">Object Name</Label>
                                <Input
                                  placeholder="e.g. Cursor_Team__c"
                                  value={customObjectName}
                                  onChange={(e) => setCustomObjectName(e.target.value)}
                                  className="h-7 text-xs font-mono"
                                />
                              </div>
                              <div className="space-y-1">
                                <Label className="text-xs">Filter Field</Label>
                                <Input
                                  placeholder="e.g. Account__c"
                                  value={customObjectFilterField}
                                  onChange={(e) => setCustomObjectFilterField(e.target.value)}
                                  className="h-7 text-xs font-mono"
                                />
                              </div>
                            </div>
                            <div className="space-y-1">
                              <Label className="text-xs">Fields (optional, comma-separated)</Label>
                              <Input
                                placeholder="e.g. Id, Name, Team_ID__c, Num_Active_Core_Users_L30D__c"
                                value={customObjectFieldsInput}
                                onChange={(e) => setCustomObjectFieldsInput(e.target.value)}
                                className="h-7 text-xs font-mono"
                              />
                            </div>
                            <div className="w-24 space-y-1">
                              <Label className="text-xs">Limit</Label>
                              <Input
                                type="number"
                                placeholder="50"
                                value={customObjectLimit}
                                onChange={(e) => setCustomObjectLimit(e.target.value)}
                                className="h-7 text-xs"
                              />
                            </div>
                          </div>
                        )}

                        {/* Field Mappings - Full Editor */}
                        <div className="space-y-3 border-t pt-3">
                          <div className="flex items-center justify-between">
                            <Label className="text-xs font-medium">
                              Default Field Mappings
                              {isFetchingCrmProperties && (
                                <Loader2 className="ml-2 inline h-3 w-3 animate-spin" />
                              )}
                            </Label>
                          </div>
                          <p className="text-xs text-muted-foreground">
                            Configure which Cedar fields map to {integrationInfo.name} fields. Users
                            can customize these mappings in their settings.
                          </p>

                          {/* Existing Mappings */}
                          <div className="max-h-[400px] space-y-3 overflow-y-auto rounded border bg-background p-3">
                            {crmFieldMappings.length > 0 ? (
                              crmFieldMappings.map((mapping) => {
                                const isSimple = isSimpleMapping(mapping);
                                return (
                                  <div
                                    key=[redacted]
                                    className="space-y-2 rounded-lg border bg-muted/30 p-3"
                                  >
                                    <div className="flex items-center justify-between">
                                      {/* CRM Field Selector */}
                                      <div className="flex-1 mr-2">
                                        {crmPropertiesData?.field_names && crmPropertiesData.field_names.length > 0 ? (
                                          <Popover>
                                            <PopoverTrigger asChild>
                                              <Button
                                                variant="outline"
                                                size="sm"
                                                className="h-8 w-full justify-between font-mono text-xs"
                                              >
                                                {mapping.crmFieldName || 'Select CRM field...'}
                                                <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                                              </Button>
                                            </PopoverTrigger>
                                            <PopoverContent className="w-[300px] p-0">
                                              <Command>
                                                <CommandInput placeholder="Search CRM fields..." />
                                                <CommandList>
                                                  <CommandEmpty>No CRM field found.</CommandEmpty>
                                                  <CommandGroup>
                                                    {crmPropertiesData.field_names.map((field) => {
                                                      const isMapped = crmFieldMappings.some(
                                                        (m) =>
                                                          m.crmFieldName === field &&
                                                          m.crmFieldName !== mapping.crmFieldName,
                                                      );
                                                      const isSelected = mapping.crmFieldName === field;
                                                      const hasPicklist =
                                                        !!crmPropertiesData.picklist_fields?.[field];
                                                      return (
                                                        <CommandItem
                                                          key=[redacted]
                                                          value={field}
                                                          disabled={isMapped}
                                                          onSelect={() => {
                                                            handleCrmFieldNameChange(
                                                              mapping.crmFieldName,
                                                              field,
                                                            );
                                                          }}
                                                          className={
                                                            isMapped ? 'opacity-50' : undefined
                                                          }
                                                        >
                                                          <Check
                                                            className={`mr-2 h-4 w-4 ${
                                                              isSelected ? 'opacity-100' : 'opacity-0'
                                                            }`}
                                                          />
                                                          <span className="font-mono text-xs">
                                                            {field}
                                                          </span>
                                                          {hasPicklist && (
                                                            <span className="ml-2 text-xs text-blue-500">
                                                              (picklist)
                                                            </span>
                                                          )}
                                                          {isMapped && (
                                                            <span className="ml-2 text-xs text-muted-foreground">
                                                              (mapped)
                                                            </span>
                                                          )}
                                                        </CommandItem>
                                                      );
                                                    })}
                                                  </CommandGroup>
                                                </CommandList>
                                              </Command>
                                            </PopoverContent>
                                          </Popover>
                                        ) : (
                                          <Input
                                            value={mapping.crmFieldName}
                                            onChange={(e) =>
                                              handleCrmFieldNameChange(
                                                mapping.crmFieldName,
                                                e.target.value,
                                              )
                                            }
                                            className="h-8 font-mono text-xs"
                                            placeholder="CRM field name"
                                          />
                                        )}
                                      </div>

                                      {/* Mapping Type Toggle */}
                                      <ToggleGroup
                                        type="single"
                                        value={isSimple ? 'simple' : 'template'}
                                        onValueChange={(value) => {
                                          if (value)
                                            handleToggleMappingType(
                                              mapping.crmFieldName,
                                              value === 'simple',
                                            );
                                        }}
                                        className="mr-2"
                                      >
                                        <ToggleGroupItem
                                          value="simple"
                                          size="sm"
                                          className="h-8 px-2 text-xs"
                                        >
                                          Direct
                                        </ToggleGroupItem>
                                        <ToggleGroupItem
                                          value="template"
                                          size="sm"
                                          className="h-8 px-2 text-xs"
                                        >
                                          Template
                                        </ToggleGroupItem>
                                      </ToggleGroup>

                                      {/* Remove Button */}
                                      <Button
                                        variant="ghost"
                                        size="sm"
                                        className="h-8 w-8 p-0 text-red-600 hover:text-red-700"
                                        onClick={() => handleRemoveMapping(mapping.crmFieldName)}
                                      >
                                        <X className="h-4 w-4" />
                                      </Button>
                                    </div>

                                    {/* Mapping Value */}
                                    {isSimple ? (
                                      <Select
                                        value={
                                          isSimpleMapping(mapping) ? mapping.cedarFieldName : ''
                                        }
                                        onValueChange={(value) =>
                                          handleSimpleMappingChange(mapping.crmFieldName, value)
                                        }
                                      >
                                        <SelectTrigger >
                                          <SelectValue placeholder="Select Cedar field..." />
                                        </SelectTrigger>
                                        <SelectContent>
                                          {availableCedarFields.map((field) => (
                                            <SelectItem
                                              key=[redacted]
                                              value={field.value}
                                              className="text-xs"
                                            >
                                              {field.label}
                                            </SelectItem>
                                          ))}
                                        </SelectContent>
                                      </Select>
                                    ) : (
                                      <div className="space-y-3">
                                        <div>
                                          <Label className="text-xs text-muted-foreground mb-1 block">
                                            Template (use {'{variable}'} for placeholders)
                                          </Label>
                                          <div className="flex gap-2">
                                            <Input
                                              id={`template-${mapping.crmFieldName}`}
                                              value={isComplexMapping(mapping) ? mapping.template : ''}
                                              onChange={(e) =>
                                                handleComplexMappingChange(
                                                  mapping.crmFieldName,
                                                  e.target.value,
                                                  isComplexMapping(mapping)
                                                    ? mapping.transformations
                                                    : undefined,
                                                  isComplexMapping(mapping)
                                                    ? mapping.allowedValues
                                                    : undefined,
                                                  isComplexMapping(mapping) ? mapping.prefix : undefined,
                                                )
                                              }
                                              placeholder="{nextStepDate} – {nextSteps}"
                                              className="text-xs font-mono flex-1 h-8"
                                            />
                                            <Select
                                              onValueChange={(value) => {
                                                const input = document.getElementById(
                                                  `template-${mapping.crmFieldName}`,
                                                ) as HTMLInputElement;
                                                if (input) {
                                                  const start = input.selectionStart || 0;
                                                  const end = input.selectionEnd || 0;
                                                  const currentValue = isComplexMapping(mapping)
                                                    ? mapping.template
                                                    : '';
                                                  const newValue =
                                                    currentValue.slice(0, start) +
                                                    `{${value}}` +
                                                    currentValue.slice(end);
                                                  handleComplexMappingChange(
                                                    mapping.crmFieldName,
                                                    newValue,
                                                    isComplexMapping(mapping)
                                                      ? mapping.transformations
                                                      : undefined,
                                                    isComplexMapping(mapping)
                                                      ? mapping.allowedValues
                                                      : undefined,
                                                    isComplexMapping(mapping) ? mapping.prefix : undefined,
                                                  );
                                                  // Set cursor position after inserted variable
                                                  setTimeout(() => {
                                                    input.focus();
                                                    const newCursorPos = start + value.length + 2; // +2 for { and }
                                                    input.setSelectionRange(newCursorPos, newCursorPos);
                                                  }, 0);
                                                }
                                              }}
                                            >
                                              <SelectTrigger className="w-[140px]">
                                                <Plus className="h-3 w-3 mr-1" />
                                                <span>Insert Variable</span>
                                              </SelectTrigger>
                                              <SelectContent>
                                                {availableCedarFields.map((field) => (
                                                  <SelectItem key=[redacted] value={field.value}>
                                                    {field.label}
                                                  </SelectItem>
                                                ))}
                                              </SelectContent>
                                            </Select>
                                          </div>
                                        </div>
                                        <div>
                                          <Label className="text-xs text-muted-foreground mb-1 block">
                                            Prefix (optional, use {'{variable}'} for placeholders)
                                          </Label>
                                          <div className="flex gap-2">
                                            <Input
                                              id={`prefix-${mapping.crmFieldName}`}
                                              value={isComplexMapping(mapping) ? mapping.prefix || '' : ''}
                                              onChange={(e) =>
                                                handleComplexMappingChange(
                                                  mapping.crmFieldName,
                                                  isComplexMapping(mapping) ? mapping.template : '',
                                                  isComplexMapping(mapping)
                                                    ? mapping.transformations
                                                    : undefined,
                                                  isComplexMapping(mapping)
                                                    ? mapping.allowedValues
                                                    : undefined,
                                                  e.target.value || undefined,
                                                )
                                              }
                                              placeholder="MS:  or {status}: "
                                              className="text-xs font-mono flex-1 h-8"
                                            />
                                            <Select
                                              onValueChange={(value) => {
                                                const input = document.getElementById(
                                                  `prefix-${mapping.crmFieldName}`,
                                                ) as HTMLInputElement;
                                                if (input) {
                                                  const start = input.selectionStart || 0;
                                                  const end = input.selectionEnd || 0;
                                                  const currentValue = isComplexMapping(mapping)
                                                    ? mapping.prefix || ''
                                                    : '';
                                                  const newValue =
                                                    currentValue.slice(0, start) +
                                                    `{${value}}` +
                                                    currentValue.slice(end);
                                                  handleComplexMappingChange(
                                                    mapping.crmFieldName,
                                                    isComplexMapping(mapping) ? mapping.template : '',
                                                    isComplexMapping(mapping)
                                                      ? mapping.transformations
                                                      : undefined,
                                                    isComplexMapping(mapping)
                                                      ? mapping.allowedValues
                                                      : undefined,
                                                    newValue || undefined,
                                                  );
                                                  // Set cursor position after inserted variable
                                                  setTimeout(() => {
                                                    input.focus();
                                                    const newCursorPos = start + value.length + 2; // +2 for { and }
                                                    input.setSelectionRange(newCursorPos, newCursorPos);
                                                  }, 0);
                                                }
                                              }}
                                            >
                                              <SelectTrigger className="w-[140px]">
                                                <Plus className="h-3 w-3 mr-1" />
                                                <span>Insert Variable</span>
                                              </SelectTrigger>
                                              <SelectContent>
                                                {availableCedarFields.map((field) => (
                                                  <SelectItem key=[redacted] value={field.value}>
                                                    {field.label}
                                                  </SelectItem>
                                                ))}
                                              </SelectContent>
                                            </Select>
                                          </div>
                                        </div>
                                        {/* Transformations UI */}
                                        {isComplexMapping(mapping) &&
                                          (mapping.template || mapping.prefix) && (
                                            <div className="space-y-2">
                                              {(() => {
                                                // Extract placeholders from both template and prefix
                                                const templatePlaceholders =
                                                  mapping.template?.match(/\{([^}]+)\}/g) || [];
                                                const prefixPlaceholders =
                                                  mapping.prefix?.match(/\{([^}]+)\}/g) || [];
                                                const allPlaceholders = [
                                                  ...new Set([...templatePlaceholders, ...prefixPlaceholders]),
                                                ];
                                                return allPlaceholders.map((placeholder) => {
                                                  const fieldName = placeholder.replace(/[{}]/g, '');
                                                  const transformation = mapping.transformations?.[fieldName];
                                                  return (
                                                    <div
                                                      key=[redacted]
                                                      className="flex items-center gap-2 text-xs"
                                                    >
                                                      <Label className="text-muted-foreground min-w-[100px]">
                                                        {fieldName}:
                                                      </Label>
                                                      <Select
                                                        value={transformation?.type || 'none'}
                                                        onValueChange={(value) => {
                                                          const newTransformations: Record<
                                                            string,
                                                            {
                                                              type: 'date' | 'number' | 'string';
                                                              format?: string;
                                                            }
                                                          > = {};
                                                          if (
                                                            value !== 'none' &&
                                                            (value === 'date' ||
                                                              value === 'number' ||
                                                              value === 'string')
                                                          ) {
                                                            Object.keys(
                                                              mapping.transformations || {},
                                                            ).forEach((key) => {
                                                              if (
                                                                key !== fieldName &&
                                                                mapping.transformations?.[key]
                                                              ) {
                                                                const trans = mapping.transformations[key];
                                                                if (
                                                                  trans.type === 'date' ||
                                                                  trans.type === 'number' ||
                                                                  trans.type === 'string'
                                                                ) {
                                                                  newTransformations[key] = {
                                                                    type: trans.type,
                                                                    format: trans.format,
                                                                  };
                                                                }
                                                              }
                                                            });
                                                            newTransformations[fieldName] = {
                                                              type: value,
                                                              format: transformation?.format,
                                                            };
                                                          } else {
                                                            // Keep other transformations, just remove this one
                                                            Object.keys(
                                                              mapping.transformations || {},
                                                            ).forEach((key) => {
                                                              if (
                                                                key !== fieldName &&
                                                                mapping.transformations?.[key]
                                                              ) {
                                                                const trans = mapping.transformations[key];
                                                                if (
                                                                  trans.type === 'date' ||
                                                                  trans.type === 'number' ||
                                                                  trans.type === 'string'
                                                                ) {
                                                                  newTransformations[key] = {
                                                                    type: trans.type,
                                                                    format: trans.format,
                                                                  };
                                                                }
                                                              }
                                                            });
                                                          }
                                                          handleComplexMappingChange(
                                                            mapping.crmFieldName,
                                                            mapping.template,
                                                            Object.keys(newTransformations).length > 0
                                                              ? newTransformations
                                                              : undefined,
                                                            mapping.allowedValues,
                                                            mapping.prefix,
                                                          );
                                                        }}
                                                      >
                                                        <SelectTrigger size="sm" >
                                                          <SelectValue />
                                                        </SelectTrigger>
                                                        <SelectContent>
                                                          <SelectItem value="none">
                                                            No transformation
                                                          </SelectItem>
                                                          <SelectItem value="date">Date</SelectItem>
                                                          <SelectItem value="number">Number</SelectItem>
                                                          <SelectItem value="string">String</SelectItem>
                                                        </SelectContent>
                                                      </Select>
                                                      {transformation?.type === 'date' && (
                                                        <Select
                                                          value={
                                                            transformation.format &&
                                                            DATE_FORMAT_OPTIONS.find(
                                                              (opt) => opt.value === transformation.format,
                                                            )
                                                              ? transformation.format
                                                              : 'custom'
                                                          }
                                                          onValueChange={(value) => {
                                                            if (value === 'custom') return;
                                                            const newTransformations: Record<
                                                              string,
                                                              {
                                                                type: 'date' | 'number' | 'string';
                                                                format?: string;
                                                              }
                                                            > = {};
                                                            Object.keys(
                                                              mapping.transformations || {},
                                                            ).forEach((key) => {
                                                              if (mapping.transformations?.[key]) {
                                                                const trans = mapping.transformations[key];
                                                                if (
                                                                  trans.type === 'date' ||
                                                                  trans.type === 'number' ||
                                                                  trans.type === 'string'
                                                                ) {
                                                                  newTransformations[key] = {
                                                                    type: trans.type,
                                                                    format:
                                                                      key === fieldName ? value : trans.format,
                                                                  };
                                                                }
                                                              }
                                                            });
                                                            handleComplexMappingChange(
                                                              mapping.crmFieldName,
                                                              mapping.template,
                                                              Object.keys(newTransformations).length > 0
                                                                ? newTransformations
                                                                : undefined,
                                                              mapping.allowedValues,
                                                              mapping.prefix,
                                                            );
                                                          }}
                                                        >
                                                          <SelectTrigger size="sm" className="w-[180px]">
                                                            <SelectValue />
                                                          </SelectTrigger>
                                                          <SelectContent>
                                                            {DATE_FORMAT_OPTIONS.map((opt) => (
                                                              <SelectItem key=[redacted] value={opt.value}>
                                                                {opt.value} ({opt.example})
                                                              </SelectItem>
                                                            ))}
                                                          </SelectContent>
                                                        </Select>
                                                      )}
                                                    </div>
                                                  );
                                                });
                                              })()}
                                            </div>
                                          )}
                                      </div>
                                    )}

                                    {/* Allowed Values */}
                                    <div className="pt-1">
                                      <Label className="text-xs text-muted-foreground">
                                        Allowed values (optional, comma-separated):
                                      </Label>
                                      <Input
                                        value={
                                          (isSimpleMapping(mapping) || isComplexMapping(mapping)
                                            ? mapping.allowedValues
                                            : undefined
                                          )?.join(', ') || ''
                                        }
                                        onChange={(e) => {
                                          const values = e.target.value
                                            .split(',')
                                            .map((v) => v.trim())
                                            .filter(Boolean);
                                          handleAllowedValuesChange(mapping.crmFieldName, values);
                                        }}
                                        placeholder="value1, value2, value3"
                                        className="mt-1 h-7 text-xs"
                                      />
                                    </div>
                                  </div>
                                );
                              })
                            ) : (
                              <p className="py-4 text-center text-xs text-muted-foreground">
                                No field mappings configured. Click below to add a mapping.
                              </p>
                            )}
                          </div>

                          {/* Add New Mapping */}
                          {crmPropertiesData?.field_names && crmPropertiesData.field_names.length > 0 ? (
                            <Popover>
                              <PopoverTrigger asChild>
                                <Button
                                  variant="outline"
                                  size="sm"
                                  className="w-full justify-start gap-2"
                                >
                                  <Plus className="h-4 w-4" />
                                  Add field mapping
                                </Button>
                              </PopoverTrigger>
                              <PopoverContent className="w-[300px] p-0">
                                <Command>
                                  <CommandInput placeholder="Search CRM fields..." />
                                  <CommandList>
                                    <CommandEmpty>No CRM field found.</CommandEmpty>
                                    <CommandGroup>
                                      {crmPropertiesData.field_names.map((field) => {
                                        const isMapped = crmFieldMappings.some(
                                          (m) => m.crmFieldName === field,
                                        );
                                        const hasPicklist =
                                          !!crmPropertiesData.picklist_fields?.[field];
                                        return (
                                          <CommandItem
                                            key=[redacted]
                                            value={field}
                                            disabled={isMapped}
                                            onSelect={() => handleAddMapping(field)}
                                            className={isMapped ? 'opacity-50' : undefined}
                                          >
                                            <span className="font-mono text-xs">{field}</span>
                                            {hasPicklist && (
                                              <span className="ml-2 text-xs text-blue-500">
                                                (picklist)
                                              </span>
                                            )}
                                            {isMapped && (
                                              <span className="ml-2 text-xs text-muted-foreground">
                                                (already mapped)
                                              </span>
                                            )}
                                          </CommandItem>
                                        );
                                      })}
                                    </CommandGroup>
                                  </CommandList>
                                </Command>
                              </PopoverContent>
                            </Popover>
                          ) : (
                            <Button
                              variant="outline"
                              size="sm"
                              className="w-full justify-start gap-2"
                              onClick={() => handleAddMapping('new_field')}
                              disabled={isFetchingCrmProperties}
                            >
                              {isFetchingCrmProperties ? (
                                <Loader2 className="h-4 w-4 animate-spin" />
                              ) : (
                                <Plus className="h-4 w-4" />
                              )}
                              {isFetchingCrmProperties
                                ? 'Loading CRM fields...'
                                : 'Add field mapping'}
                            </Button>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                )}

              </div>

              {/* Dialog Footer - show for API key, manual with org webhooks, CRM, or when configured (for remove) */}
              {(effectiveConnectionType === 'api_key' || effectiveConnectionType === 'manual' || isCrmProvider || isConfigured) && (
                <DialogFooter className="flex-row gap-2 sm:justify-between">
                  {isConfigured && effectiveConnectionType !== 'manual' && (
                    <Dialog>
                      <DialogTrigger asChild>
                        <Button variant="outline" size="sm" className="text-red-600">
                          <Trash2 className="mr-2 h-3 w-3" />
                          Remove
                        </Button>
                      </DialogTrigger>
                      <DialogContent>
                        <DialogHeader>
                          <DialogTitle>Remove Configuration</DialogTitle>
                          <DialogDescription>
                            Are you sure you want to remove the {integrationInfo.name}{' '}
                            configuration? Team members will need to connect their own accounts.
                          </DialogDescription>
                        </DialogHeader>
                        <div className="flex justify-end gap-4">
                          <DialogClose asChild>
                            <Button variant="outline">Cancel</Button>
                          </DialogClose>
                          <DialogClose asChild>
                            <Button
                              variant="destructive"
                              onClick={handleRemoveConfig}
                              disabled={isRemoving}
                            >
                              {isRemoving ? (
                                <>
                                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                  Removing...
                                </>
                              ) : (
                                'Remove'
                              )}
                            </Button>
                          </DialogClose>
                        </div>
                      </DialogContent>
                    </Dialog>
                  )}
                  {/* Manual types with org webhooks - Enable/Disable button */}
                  {effectiveConnectionType === 'manual' && (
                    <div className="flex flex-1 justify-end gap-2">
                      <DialogClose asChild>
                        <Button variant="outline" size="sm">
                          Cancel
                        </Button>
                      </DialogClose>
                      <Button
                        size="sm"
                        variant={isConfigured ? 'destructive' : 'default'}
                        onClick={handleToggleEnabled}
                        disabled={isTogglingEnabled}
                      >
                        {isTogglingEnabled ? (
                          <>
                            <Loader2 className="mr-2 h-3 w-3 animate-spin" />
                            {isConfigured ? 'Disabling...' : 'Enabling...'}
                          </>
                        ) : isConfigured ? (
                          'Disable'
                        ) : (
                          'Enable'
                        )}
                      </Button>
                    </div>
                  )}
                  {(effectiveConnectionType === 'api_key' || (isCrmProvider && effectiveConnectionType !== 'manual')) && (
                    <div className="flex flex-1 justify-end gap-2">
                      <DialogClose asChild>
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setFormFields({})}
                          disabled={isSaving}
                        >
                          Cancel
                        </Button>
                      </DialogClose>
                      <Button size="sm" onClick={handleSaveConfig} disabled={isSaving}>
                        {isSaving ? (
                          <>
                            <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                            Saving...
                          </>
                        ) : (
                          'Save Configuration'
                        )}
                      </Button>
                    </div>
                  )}
                </DialogFooter>
              )}
            </DialogContent>
          </Dialog>
          )}

          {/* Quick remove button on card (only when configured) */}
          {isConfigured && effectiveConnectionType !== 'manual' && (
            <Dialog>
              <DialogTrigger asChild>
                <Button variant="outline" size="sm" className="px-2">
                  <Trash2 className="h-3 w-3 text-red-500" />
                </Button>
              </DialogTrigger>
              <DialogContent>
                <DialogHeader>
                  <DialogTitle>Remove Configuration</DialogTitle>
                  <DialogDescription>
                    Are you sure you want to remove the {integrationInfo.name} configuration? Team
                    members will need to connect their own accounts.
                  </DialogDescription>
                </DialogHeader>
                <div className="flex justify-end gap-4">
                  <DialogClose asChild>
                    <Button variant="outline">Cancel</Button>
                  </DialogClose>
                  <DialogClose asChild>
                    <Button
                      variant="destructive"
                      onClick={handleRemoveConfig}
                      disabled={isRemoving}
                    >
                      {isRemoving ? (
                        <>
                          <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                          Removing...
                        </>
                      ) : (
                        'Remove'
                      )}
                    </Button>
                  </DialogClose>
                </div>
              </DialogContent>
            </Dialog>
          )}
        </div>
      )}
    </div>
  );
}