import React, { useState, useMemo, useEffect, useRef, useCallback } from 'react';
import { RefreshCw, AlertCircle } from 'lucide-react';
import { BaseModal, Button } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';

export interface CrmConvertLeadActionInput {
    label: string;
    name: string;
    type: string;
    required?: boolean;
    referenceTo?: string;
    uiSection?: string;
    uiMode?: 'create' | 'reuse' | 'skip' | 'hidden' | string;
    targetObject?: string;
    targetFieldAPIName?: string;
    requiredPicklistTag?: string;
    mappingSourceObject?: string;
    mappingActionType?: string;
    prefillSourceFieldAPIName?: string;
    targetRequired?: boolean;
    targetDefaulted?: boolean;
    maxLength?: number;
    defaulted?: boolean;
    defaultValue?: unknown;
    description?: string;
}

export interface CrmConvertLeadActionOutput {
    label?: string;
    name: string;
    type?: string;
    referenceTo?: string;
    description?: string;
}

export interface CrmConvertLeadInputGuardSummary {
    gatedInput: string;
    requiredPermission?: string;
    requiredObject?: string;
    requiredOperation?: string;
    condition?: string;
    callerHasPermission: boolean;
}

export interface CrmConvertLeadAction {
    name: string;
    label: string;
    endpoint?: string;
    previewEndpoint?: string;
    inputs?: readonly CrmConvertLeadActionInput[];
    outputs?: readonly CrmConvertLeadActionOutput[];
    config?: Record<string, unknown>;
    inputGuards?: readonly CrmConvertLeadInputGuardSummary[];
}

export interface CrmConvertLeadPicklistValue {
    value: string;
    label?: string;
    active?: boolean;
    tags?: readonly string[];
}

export interface CrmConvertLeadField {
    name: string;
    label?: string;
    type?: string;
    picklistValues?: readonly CrmConvertLeadPicklistValue[];
}

export interface CrmConvertLeadObjectMetadata {
    name: string;
    label?: string;
    fields?: readonly CrmConvertLeadField[];
}

export type CrmConvertLeadRecord = Record<string, unknown>;

export interface CrmConvertLeadCreatePreviewImage {
    object: string;
    fields: Record<string, unknown>;
    siblingMaxDefaultedFields?: string[] | null;
}

export interface CrmConvertLeadChildPreview {
    object: string;
    count: number;
    rows?: Record<string, unknown>[];
}

export interface CrmConvertLeadPreviewResult {
    actionName?: string;
    isSuccess?: boolean;
    parentPreview?: CrmConvertLeadCreatePreviewImage | null;
    childPreview?: CrmConvertLeadChildPreview[] | null;
    errors?: Array<{ message?: string; statusCode?: string }> | null;
}

export interface CrmConvertLeadApi {
    query: (request: {
        objectApiName: string;
        selectFields: string[];
        filterExpr: string;
        limit: number;
    }) => Promise<CrmConvertLeadRecord[]>;
    previewStandardAction: (
        actionPreviewEndpoint: string,
        input: Record<string, unknown>,
    ) => Promise<CrmConvertLeadPreviewResult>;
    executeStandardAction: (
        actionEndpoint: string,
        inputs: Record<string, unknown>[],
    ) => Promise<Record<string, unknown>>;
    getSchema: (objectApiName: string) => Promise<{ schema?: CrmConvertLeadObjectMetadata | null }>;
    warn: (message: string, context?: Record<string, unknown>, error?: unknown) => void;
}

export interface CrmConvertLeadHost {
    navigateToNewRecord: (objectApiName: string) => void;
    navigateToRecord: (objectApiName: string, recordId: string) => void;
    refreshRecord: () => void;
}

export interface CrmConvertLeadLookupProps {
    ObjectApiName: string | string[];
    value: string | null | undefined;
    onChange: (value: string | null, record?: CrmConvertLeadRecord) => void;
    disabled?: boolean;
    placeholder?: string;
    error?: boolean;
    objectType?: string;
    returnFields?: string[];
    excludeIds?: string[];
    lookupContext?: {
        sourceObject: string;
        sourceField: string;
        recordContext: Record<string, unknown>;
    };
    inputAutoComplete?: string;
}

export interface CrmConvertLeadModalProps {
    isOpen: boolean;
    onClose: () => void;
    record: CrmConvertLeadRecord;
    objectMetadata: CrmConvertLeadObjectMetadata;
    action: CrmConvertLeadAction;
    host: CrmConvertLeadHost;
    api: CrmConvertLeadApi;
    lookupComponent: React.ComponentType<CrmConvertLeadLookupProps>;
}

type ContactSelection = 'create' | 'reuse';
type OpportunitySelection = 'create' | 'reuse' | 'skip';

interface CampaignAttributionPreviewRow {
    label: string;
    value: string;
}

interface CampaignAttributionPreviewData {
    title: string;
    summary?: string;
    rows: CampaignAttributionPreviewRow[];
    warnings: string[];
}

interface ContactMatchConfig {
    accountInput: 'accountId';
    emailField: string;
    targetInput: 'contactId';
    switchModeTo: 'reuse';
}

function stringFromRecord(record: CrmConvertLeadRecord, fieldName?: string): string {
    if (!fieldName) {
        return '';
    }
    const value = record[fieldName];
    if (value === undefined || value === null) {
        return '';
    }
    return String(value);
}

function initialCreateInputValue(input: CrmConvertLeadActionInput, record: CrmConvertLeadRecord): string {
    if (input.defaultValue !== undefined && input.defaultValue !== null) {
        return String(input.defaultValue);
    }
    return stringFromRecord(record, input.prefillSourceFieldAPIName);
}

function createInputLabel(input: CrmConvertLeadActionInput): string {
    return input.label || input.targetFieldAPIName || input.name;
}

function readRecord(value: unknown): Record<string, unknown> | null {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return null;
    }
    return value as Record<string, unknown>;
}

function readString(value: unknown): string | undefined {
    return typeof value === 'string' && value.trim() ? value.trim() : undefined;
}

function readStringArray(value: unknown): string[] {
    if (!Array.isArray(value)) {
        return [];
    }
    return value
        .map(readString)
        .filter((entry): entry is string => !!entry);
}

function readCampaignAttributionPreview(config: Record<string, unknown> | undefined): CampaignAttributionPreviewData | null {
    // Path A: structured format from static action config (legacy / future explicit payload).
    const preview = readRecord(config?.campaignAttributionPreview);
    if (preview) {
        const rows = Array.isArray(preview.rows)
            ? preview.rows
                .map(readRecord)
                .filter((row): row is Record<string, unknown> => !!row)
                .map((row) => {
                    const label = readString(row.label);
                    const value = readString(row.value);
                    if (!label || !value) {
                        return null;
                    }
                    return { label, value };
                })
                .filter((row): row is CampaignAttributionPreviewRow => !!row)
            : [];
        const warnings = readStringArray(preview.warnings);
        const summary = readString(preview.summary);

        if (summary || rows.length > 0 || warnings.length > 0) {
            return {
                title: readString(preview.title) || 'Campaign Attribution',
                summary,
                rows,
                warnings,
            };
        }
    }

    // Path B: individual flow output variables from Std_ConvertLeadCampaignPreview
    // (merged into action.config by ActionRendererHost via previewFlowDeveloperName).
    // Only active when the flow has run — detected by campaignFound being a boolean.
    if (typeof config?.campaignFound === 'boolean') {
        if (config.campaignFound) {
            const name = readString(config.campaignName) || '';
            return {
                title: 'Campaign Attribution',
                rows: name ? [{ label: 'Campaign', value: name }] : [],
                warnings: [],
            };
        }
        return {
            title: 'Campaign Attribution',
            rows: [],
            warnings: ['No Campaign Source — the Opportunity will not be attributed to a Campaign.'],
        };
    }

    return null;
}

function readContactMatchConfig(config: Record<string, unknown> | undefined): ContactMatchConfig | null {
    const leadConvertMatch = readRecord(config?.leadConvertMatch);
    const contactByAccountAndEmail = readRecord(leadConvertMatch?.contactByAccountAndEmail);
    if (!contactByAccountAndEmail || contactByAccountAndEmail.enabled !== true) {
        return null;
    }

    const accountInput = readString(contactByAccountAndEmail.accountInput);
    const emailField = readString(contactByAccountAndEmail.emailField);
    const targetInput = readString(contactByAccountAndEmail.targetInput);
    const switchModeTo = readString(contactByAccountAndEmail.switchModeTo);

    if (
        accountInput !== 'accountId' ||
        !emailField ||
        targetInput !== 'contactId' ||
        switchModeTo !== 'reuse'
    ) {
        return null;
    }

    return {
        accountInput,
        emailField,
        targetInput,
        switchModeTo,
    };
}

function escapeSoqlValue(value: string): string {
    return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
}

export const CrmConvertLeadModal: React.FC<CrmConvertLeadModalProps> = ({
    isOpen,
    onClose,
    record,
    objectMetadata,
    action,
    host,
    api,
    lookupComponent: LookupComponent,
}) => {
    const actionInputs = useMemo(() => action.inputs || [], [action.inputs]);
    const inputByName = useMemo(() => {
        return new Map(actionInputs.map(input => [input.name, input]));
    }, [actionInputs]);
    const inputGuards = useMemo(() => action.inputGuards || [], [action.inputGuards]);
    const deniedInputNames = useMemo(() => {
        return new Set(
            inputGuards
                .filter(guard => {
                    if (!guard.gatedInput || guard.callerHasPermission) {
                        return false;
                    }
                    if ((guard.gatedInput === 'accountId' || guard.gatedInput === 'contactId') &&
                        guard.requiredOperation === 'Create') {
                        return false;
                    }
                    return true;
                })
                .map(guard => guard.gatedInput as string),
        );
    }, [inputGuards]);
    const hasInput = (name: string) => inputByName.has(name);
    const hasUsableInput = (name: string) => hasInput(name) && !deniedInputNames.has(name);
    const hasDeniedGuard = (name: string, operation?: string) => inputGuards.some(guard =>
        guard.gatedInput === name &&
        !guard.callerHasPermission &&
        (!operation || guard.requiredOperation === operation),
    );
    const isRequiredInput = (name: string) => !!inputByName.get(name)?.required;
    const referenceTarget = (name: string) => inputByName.get(name)?.referenceTo;
    const hasServerDefault = (name: string) => {
        const input = inputByName.get(name);
        return !!input?.defaulted || input?.defaultValue !== undefined;
    };
    const stringDefault = (name: string) => {
        const value = inputByName.get(name)?.defaultValue;
        if (value === undefined || value === null) {
            return '';
        }
        return String(value);
    };
    const booleanDefault = (name: string) => inputByName.get(name)?.defaultValue === true;
    const statusInputRequired = hasUsableInput('convertedStatus') && isRequiredInput('convertedStatus');
    const accountInputRequired = hasUsableInput('accountId') && isRequiredInput('accountId');
    const accountHasServerDefault = hasServerDefault('accountId');
    const showConvertedStatus = hasUsableInput('convertedStatus') && !hasServerDefault('convertedStatus');
    const statusRequiresLocalValue = statusInputRequired && !hasServerDefault('convertedStatus');
    const accountTarget = referenceTarget('accountId');
    const contactTarget = referenceTarget('contactId');
    const opportunityTarget = referenceTarget('opportunityId');
    const ownerTarget = referenceTarget('ownerId');
    const convertedStatusDefault = stringDefault('convertedStatus');
    const accountIdDefault = stringDefault('accountId');
    const contactIdDefault = stringDefault('contactId');
    const opportunityIdDefault = stringDefault('opportunityId');
    const ownerIdDefault = stringDefault('ownerId');
    const doNotCreateOpportunityDefault = booleanDefault('doNotCreateOpportunity');
    const overwriteLeadSourceDefault = booleanDefault('overwriteLeadSource');
    const createInputs = useMemo(() => {
        return actionInputs.filter(input =>
            input.uiMode === 'create' &&
            !!input.targetObject &&
            !!input.targetFieldAPIName &&
            !deniedInputNames.has(input.name),
        );
    }, [actionInputs, deniedInputNames]);
    const contactCreateInputs = useMemo(
        () => createInputs.filter(input => input.uiSection === 'Contact'),
        [createInputs],
    );
    const opportunityCreateInputs = useMemo(
        () => createInputs.filter(input => input.uiSection === 'Opportunity'),
        [createInputs],
    );
    const createInputDefaults = useMemo(() => {
        return Object.fromEntries(createInputs.map(input => [input.name, initialCreateInputValue(input, record)]));
    }, [createInputs, record]);
    const campaignAttributionPreview = useMemo(
        () => readCampaignAttributionPreview(action.config),
        [action.config],
    );

    // Server-owned Flow create preview from PR #980 backend endpoint.
    // Reflects the full convert payload so the preview matches what will actually
    // be submitted. Uses AbortController for StrictMode-safe cleanup (no dedupe
    // key set before a successful response; each mount/input-change fires a fresh
    // request and cleanup aborts any in-flight call).
    const [serverPreviewResult, setServerPreviewResult] = useState<CrmConvertLeadPreviewResult | null>(null);
    const [previewError, setPreviewError] = useState<string | null>(null);
    const [previewSchemas, setPreviewSchemas] = useState<Record<string, CrmConvertLeadObjectMetadata | null>>({});
    const previewSchemasRef = useRef(previewSchemas);
    const previewEndpoint = action.previewEndpoint;
    const leadId = record.Id !== undefined && record.Id !== null ? String(record.Id) : null;

    const contactMatchConfig = useMemo(
        () => readContactMatchConfig(action.config),
        [action.config],
    );
    const leadMatchEmail = useMemo(
        () => (contactMatchConfig ? stringFromRecord(record, contactMatchConfig.emailField).trim() : ''),
        [contactMatchConfig, record],
    );

    const accountCreateDenied = hasDeniedGuard('accountId', 'Create');
    const contactCreateDenied = hasDeniedGuard('contactId', 'Create');
    const opportunityCreateDenied = hasDeniedGuard('opportunityName', 'Create');
    const canSkipOpportunity = hasUsableInput('doNotCreateOpportunity');
    const canCreateContact = contactCreateInputs.length > 0 && !contactCreateDenied;
    const canReuseContact = hasUsableInput('contactId') && !!contactTarget;
    const canCreateOpportunity = opportunityCreateInputs.length > 0 && !opportunityCreateDenied;
    const canReuseOpportunity = hasUsableInput('opportunityId') && !!opportunityTarget;
    const initialContactSelection: ContactSelection = contactIdDefault || (!canCreateContact && canReuseContact) ? 'reuse' : 'create';
    const initialOpportunitySelection: OpportunitySelection = doNotCreateOpportunityDefault && canSkipOpportunity
        ? 'skip'
        : opportunityIdDefault && canReuseOpportunity
            ? 'reuse'
            : !canCreateOpportunity && canReuseOpportunity
                ? 'reuse'
                : !canCreateOpportunity && canSkipOpportunity
                    ? 'skip'
                    : 'create';
    const resetIdentity = useMemo(() => {
        const recordId = record.Id === undefined || record.Id === null ? '' : String(record.Id);
        const actionId = action.endpoint || action.name || '';
        return `${recordId}|${actionId}`;
    }, [action.endpoint, action.name, record.Id]);
    const [loading, setLoading] = useState(false);
    const [matchPending, setMatchPending] = useState(false);
    const [contactSelection, setContactSelection] = useState<ContactSelection>(initialContactSelection);
    const [opportunitySelection, setOpportunitySelection] = useState<OpportunitySelection>(initialOpportunitySelection);
    const [convertedStatus, setConvertedStatus] = useState(convertedStatusDefault);
    const [accountId, setAccountId] = useState<string | null>(accountIdDefault || null);
    const [contactId, setContactId] = useState<string | null>(contactIdDefault || null);
    const [opportunityId, setOpportunityId] = useState<string | null>(opportunityIdDefault || null);
    const [ownerId, setOwnerId] = useState<string | null>(ownerIdDefault || null);
    const [overwriteLeadSource, setOverwriteLeadSource] = useState(overwriteLeadSourceDefault);
    const [createValues, setCreateValues] = useState<Record<string, string>>(createInputDefaults);
    const [error, setError] = useState<string | null>(null);
    const [autoMatchedContactId, setAutoMatchedContactId] = useState<string | null>(null);
    const wasOpenRef = React.useRef(false);
    const lastResetIdentityRef = React.useRef<string | null>(null);
    const lastContactMatchRequestRef = React.useRef(0);
    const contactSelectionRef = React.useRef<ContactSelection>(initialContactSelection);
    const contactIdRef = React.useRef<string | null>(contactIdDefault || null);
    const autoMatchedContactIdRef = React.useRef<string | null>(null);
    const suppressContactAutoMatchRef = React.useRef(false);

    const statusField = objectMetadata.fields?.find(f => f.name === 'Status');
    const convertedStatusRequiredPicklistTag = inputByName.get('convertedStatus')?.requiredPicklistTag;
    const statusOptions = useMemo(() => {
        const activeOptions = statusField?.picklistValues?.filter(v => v.active) || [];
        if (!convertedStatusRequiredPicklistTag) {
            return activeOptions;
        }
        return activeOptions.filter(v => v.tags?.includes(convertedStatusRequiredPicklistTag));
    }, [statusField, convertedStatusRequiredPicklistTag]);
    const doNotCreateOpportunity = opportunitySelection === 'skip';
    const reuseModeRequiresAccount = contactSelection === 'reuse' || opportunitySelection === 'reuse';
    const accountCreateDeniedRequiresReuse = accountCreateDenied && !accountHasServerDefault;
    const accountRequiresLocalValue = hasUsableInput('accountId') && !accountHasServerDefault;
    const accountReady = !accountRequiresLocalValue || !!accountId;
    const dependentControlsDisabled = loading || !accountReady;
    const accountInputLabel = inputByName.get('accountId')?.label ||
        inputByName.get('accountId')?.targetObject ||
        accountTarget ||
        inputByName.get('accountId')?.name ||
        'Record';
    const accountCreatePermissionBlocks = accountCreateDeniedRequiresReuse && !hasUsableInput('accountId') && !accountId;
    const accountInputUnavailableForReuse =
        reuseModeRequiresAccount && hasInput('accountId') && !hasUsableInput('accountId') && !accountHasServerDefault;
    const contactReuseRequiresLocalValue = contactSelection === 'reuse' && hasUsableInput('contactId') && !contactId;
    const opportunityReuseRequiresLocalValue = opportunitySelection === 'reuse' && hasUsableInput('opportunityId') && !opportunityId;
    const contactCreatePermissionBlocks = contactSelection === 'create' && contactCreateDenied;
    const opportunityCreatePermissionBlocks = opportunitySelection === 'create' && opportunityCreateDenied;
    const modeButtonClass = (active: boolean, disabled = false) => [
        'h-9 rounded-md px-3 text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500',
        disabled
            ? 'cursor-not-allowed text-gray-400'
            : active
                ? 'bg-white text-gray-900 shadow-sm'
                : 'text-gray-600 hover:bg-white/70 hover:text-gray-900',
    ].join(' ');
    const opportunityChoiceCount = [
        canCreateOpportunity,
        canReuseOpportunity,
        canSkipOpportunity,
    ].filter(Boolean).length;
    const opportunityChoiceGridClass = opportunityChoiceCount >= 3
        ? 'grid-cols-3'
        : opportunityChoiceCount === 2
            ? 'grid-cols-2'
            : 'grid-cols-1';
    const setCreateValue = (inputName: string, value: string) => {
        setCreateValues(prev => ({ ...prev, [inputName]: value }));
    };
    const createInputValue = (inputName: string) => createValues[inputName] ?? '';
    const createInputShowsRequired = (input: CrmConvertLeadActionInput) => {
        if (hasServerDefault(input.name) || input.targetDefaulted) {
            return false;
        }
        return !!input.required || !!input.targetRequired;
    };
    const createInputRequiresLocalValue = (input: CrmConvertLeadActionInput) => {
        if (hasServerDefault(input.name) || input.targetDefaulted) {
            return false;
        }
        if (input.required) {
            return true;
        }
        if (!input.targetRequired || !input.prefillSourceFieldAPIName) {
            return false;
        }
        return Object.prototype.hasOwnProperty.call(record, input.prefillSourceFieldAPIName);
    };
    const createInputNeedsValue = (input: CrmConvertLeadActionInput) => {
        if (!createInputRequiresLocalValue(input)) {
            return false;
        }
        return createInputValue(input.name).trim() === '';
    };
    const contactCreateMissingRequired = contactSelection === 'create' && contactCreateInputs.some(createInputNeedsValue);
    const opportunityCreateMissingRequired = opportunitySelection === 'create' && opportunityCreateInputs.some(createInputNeedsValue);

    const handleCreateRelatedRecord = () => {
        if (!accountTarget) {
            return;
        }
        onClose();
        host.navigateToNewRecord(accountTarget);
    };

    React.useEffect(() => {
        const shouldReset = isOpen && (!wasOpenRef.current || lastResetIdentityRef.current !== resetIdentity);
        if (shouldReset) {
            setConvertedStatus(convertedStatusDefault);
            setAccountId(accountIdDefault || null);
            setContactId(contactIdDefault || null);
            setOpportunityId(opportunityIdDefault || null);
            setOwnerId(ownerIdDefault || null);
            setOverwriteLeadSource(overwriteLeadSourceDefault);
            setCreateValues(createInputDefaults);
            setError(null);
            setAutoMatchedContactId(null);
            setMatchPending(false);
            setContactSelection(initialContactSelection);
            setOpportunitySelection(initialOpportunitySelection);
            suppressContactAutoMatchRef.current = false;
            lastResetIdentityRef.current = resetIdentity;
        }
        if (!isOpen) {
            lastResetIdentityRef.current = null;
        }
        wasOpenRef.current = isOpen;
    }, [
        isOpen,
        resetIdentity,
        convertedStatusDefault,
        accountIdDefault,
        contactIdDefault,
        opportunityIdDefault,
        ownerIdDefault,
        overwriteLeadSourceDefault,
        createInputDefaults,
        initialContactSelection,
        initialOpportunitySelection,
    ]);

    React.useEffect(() => {
        if (contactSelection === 'create' && !canCreateContact && canReuseContact) {
            setContactSelection('reuse');
            return;
        }
        if (contactSelection === 'reuse' && !canReuseContact && canCreateContact) {
            setContactSelection('create');
        }
    }, [canCreateContact, canReuseContact, contactSelection]);

    React.useEffect(() => {
        if (opportunitySelection === 'skip' && !canSkipOpportunity) {
            setOpportunitySelection(canCreateOpportunity ? 'create' : canReuseOpportunity ? 'reuse' : 'create');
            return;
        }
        if (opportunitySelection === 'create' && !canCreateOpportunity) {
            if (canReuseOpportunity || canSkipOpportunity) {
                setOpportunitySelection(canReuseOpportunity ? 'reuse' : 'skip');
            }
            return;
        }
        if (opportunitySelection === 'reuse' && !canReuseOpportunity) {
            if (canCreateOpportunity || canSkipOpportunity) {
                setOpportunitySelection(canCreateOpportunity ? 'create' : 'skip');
            }
        }
    }, [canCreateOpportunity, canReuseOpportunity, canSkipOpportunity, opportunitySelection]);

    React.useEffect(() => {
        if (contactSelection === 'create') {
            setContactId(null);
            setOverwriteLeadSource(false);
        }
    }, [contactSelection]);

    React.useEffect(() => {
        contactSelectionRef.current = contactSelection;
        contactIdRef.current = contactId;
        autoMatchedContactIdRef.current = autoMatchedContactId;
    }, [autoMatchedContactId, contactId, contactSelection]);

    React.useEffect(() => {
        if (autoMatchedContactId && (contactSelection !== 'reuse' || contactId !== autoMatchedContactId)) {
            setAutoMatchedContactId(null);
        }
    }, [autoMatchedContactId, contactId, contactSelection]);

    React.useEffect(() => {
        if (opportunitySelection === 'skip') {
            setOpportunityId(null);
            return;
        }
        if (opportunitySelection === 'reuse') {
            return;
        }
        setOpportunityId(null);
    }, [opportunitySelection]);

    React.useEffect(() => {
        if (!contactId && overwriteLeadSource) {
            setOverwriteLeadSource(false);
        }
    }, [contactId, overwriteLeadSource]);

    React.useEffect(() => {
        if (!isOpen || !contactMatchConfig || !canReuseContact || !contactTarget) {
            return;
        }

        // SYNCHRONOUS staleness clear on every account/email transition.
        // Runs before the empty-check AND before the async query, so the
        // previous auto-match is never visible alongside a new accountId.
        if (
            autoMatchedContactIdRef.current &&
            contactSelectionRef.current === 'reuse' &&
            contactIdRef.current === autoMatchedContactIdRef.current
        ) {
            setContactId(null);
            setContactSelection(canCreateContact ? 'create' : 'reuse');
        }
        if (autoMatchedContactIdRef.current) {
            setAutoMatchedContactId(null);
        }

        if (!accountId || !leadMatchEmail) {
            return;
        }

        const requestId = lastContactMatchRequestRef.current + 1;
        lastContactMatchRequestRef.current = requestId;
        let cancelled = false;
        setMatchPending(true);

        const loadMatchedContact = async () => {
            try {
                const matches = await api.query({
                    objectApiName: contactTarget,
                    selectFields: ['Id', 'Name'],
                    filterExpr: `AccountId = '${escapeSoqlValue(accountId)}' AND ${contactMatchConfig.emailField} = '${escapeSoqlValue(leadMatchEmail)}'`,
                    limit: 2,
                });
                if (cancelled || lastContactMatchRequestRef.current !== requestId) {
                    return;
                }
                if (suppressContactAutoMatchRef.current) {
                    setMatchPending(false);
                    return;
                }

                if (matches.length >= 2) {
                    api.warn('[ConvertLeadModal] Multiple contact matches for account/email; falling back to user choice', {
                        accountId,
                        contactTarget,
                        emailField: contactMatchConfig.emailField,
                        matchCount: matches.length,
                    });
                    setMatchPending(false);
                    return;
                }

                const matchedContactId = readString(matches[0]?.Id);
                if (!matchedContactId) {
                    setMatchPending(false);
                    return;
                }

                setContactId(matchedContactId);
                setContactSelection(contactMatchConfig.switchModeTo);
                setAutoMatchedContactId(matchedContactId);
                setMatchPending(false);
            } catch (err: unknown) {
                if (!cancelled && lastContactMatchRequestRef.current === requestId) {
                    api.warn('[ConvertLeadModal] Failed to resolve account-scoped contact match', {
                        accountId,
                        contactTarget,
                        emailField: contactMatchConfig.emailField,
                    }, err);
                    setMatchPending(false);
                }
            }
        };

        void loadMatchedContact();
        return () => {
            cancelled = true;
        };
    }, [
        accountId,
        api,
        canCreateContact,
        canReuseContact,
        contactMatchConfig,
        contactTarget,
        isOpen,
        leadMatchEmail,
    ]);

    const leadName = String([record.FirstName, record.LastName].filter(Boolean).join(' ') || record.Name || 'this Lead');
    const actionEndpoint = action.endpoint;
    const requiredDeniedInput = actionInputs.find(input =>
        input.required && !hasServerDefault(input.name) && deniedInputNames.has(input.name),
    );
    const deniedDefaultForcesGuardedPath = (input: CrmConvertLeadActionInput) => {
        if (input.type === 'boolean' && input.defaultValue === false) {
            return false;
        }
        return !(
            input.name === 'doNotCreateOpportunity' &&
            input.type === 'boolean' &&
            input.defaultValue === true
        );
    };
    const blockedDefaultedDeniedInput = actionInputs.find(input =>
        deniedInputNames.has(input.name) &&
        hasServerDefault(input.name) &&
        deniedDefaultForcesGuardedPath(input),
    );
    const metadataError = (() => {
        if (!actionEndpoint) {
            return 'Action endpoint is not declared by action metadata';
        }
        if (requiredDeniedInput) {
            return `${requiredDeniedInput.label || requiredDeniedInput.name} input is not available for this user`;
        }
        if (blockedDefaultedDeniedInput) {
            return `${blockedDefaultedDeniedInput.label || blockedDefaultedDeniedInput.name} default is not available for this user`;
        }
        if (!hasInput('accountId')) {
            return 'Account input is not declared by action metadata';
        }
        if (!hasUsableInput('accountId') && !accountHasServerDefault) {
            return 'Account input is not available for this user';
        }
        if (hasUsableInput('accountId') && !accountTarget) {
            return 'Account lookup metadata is incomplete';
        }
        if (accountCreatePermissionBlocks) {
            return 'Account create path is not available for this user';
        }
        if (accountInputUnavailableForReuse) {
            return 'Account input is required when reusing a Contact or Opportunity';
        }
        if (contactCreatePermissionBlocks && !canReuseContact) {
            return 'Contact create path is not available for this user';
        }
        if (opportunityCreatePermissionBlocks && !canReuseOpportunity && !canSkipOpportunity) {
            return 'Opportunity create path is not available for this user';
        }
        if (hasUsableInput('contactId') && !contactTarget) {
            return 'Contact lookup metadata is incomplete';
        }
        if (hasUsableInput('opportunityId') && !opportunityTarget) {
            return 'Opportunity lookup metadata is incomplete';
        }
        if (hasUsableInput('ownerId') && !ownerTarget) {
            return 'Owner lookup metadata is incomplete';
        }
        return null;
    })();
    const convertDisabled =
        loading ||
        matchPending ||
        !!metadataError ||
        (accountRequiresLocalValue && !accountId) ||
        (statusRequiresLocalValue && !convertedStatus) ||
        contactReuseRequiresLocalValue ||
        opportunityReuseRequiresLocalValue ||
        contactCreateMissingRequired ||
        opportunityCreateMissingRequired ||
        contactCreatePermissionBlocks ||
        opportunityCreatePermissionBlocks;

    // Preview fires only when all required inputs are satisfied — same gate
    // as the Convert button so the preview payload matches what will be submitted.
    const previewReady = !convertDisabled;

    // Shared payload builder used by both the preview effect and handleConvert.
    // Keeps the preview in sync with the exact options that will be submitted.
    // Uses inputByName/deniedInputNames directly (stable memoized values) rather
    // than the per-render hasInput/hasUsableInput closures to satisfy exhaustive-deps.
    const buildConvertInputs = useCallback((): Record<string, unknown> => {
        const isUsable = (name: string) =>
            inputByName.has(name) && !deniedInputNames.has(name);
        const options: Record<string, unknown> = {};
        if (isUsable('accountId') && accountId) {
            options.accountId = accountId;
        }
        if (showConvertedStatus && convertedStatus) {
            options.convertedStatus = convertedStatus;
        }
        if (isUsable('contactId') && contactSelection === 'reuse' && contactId) {
            options.contactId = contactId;
        }
        if (contactSelection === 'create') {
            for (const input of contactCreateInputs) {
                const value = (createValues[input.name] ?? '').trim();
                if (value) {
                    options[input.name] = value;
                }
            }
        }
        if (inputByName.has('doNotCreateOpportunity') && opportunitySelection !== 'skip' && doNotCreateOpportunityDefault) {
            options.doNotCreateOpportunity = false;
        } else if (isUsable('doNotCreateOpportunity') && opportunitySelection === 'skip') {
            options.doNotCreateOpportunity = true;
        }
        if (opportunitySelection !== 'skip') {
            if (isUsable('opportunityId') && opportunitySelection === 'reuse' && opportunityId) {
                options.opportunityId = opportunityId;
            }
            if (opportunitySelection === 'create') {
                for (const input of opportunityCreateInputs) {
                    const value = (createValues[input.name] ?? '').trim();
                    if (value) {
                        options[input.name] = value;
                    }
                }
            }
        }
        if (isUsable('ownerId') && ownerId) {
            options.ownerId = ownerId;
        }
        if (isUsable('overwriteLeadSource') && contactSelection === 'reuse' && contactId && overwriteLeadSource) {
            options.overwriteLeadSource = true;
        }
        return options;
    }, [
        accountId,
        contactId,
        contactSelection,
        contactCreateInputs,
        convertedStatus,
        createValues,
        deniedInputNames,
        doNotCreateOpportunityDefault,
        inputByName,
        opportunityId,
        opportunitySelection,
        opportunityCreateInputs,
        ownerId,
        overwriteLeadSource,
        showConvertedStatus,
    ]);

    // Preview effect: mirrors full convert payload so the rendered preview matches
    // the operation that will actually be submitted.  AbortController ensures
    // StrictMode double-mounts abort the first call and fire a fresh one on remount.
    // A 300 ms debounce prevents rapid preview thrash when the user changes inputs.
    useEffect(() => {
        if (!isOpen || !previewEndpoint || !leadId || !previewReady) {
            setServerPreviewResult(null);
            setPreviewError(null);
            return;
        }
        const controller = new AbortController();
        // Clear stale preview immediately so the UI never shows results from a
        // prior (possibly different) set of inputs while the new fetch is in
        // flight.
        setServerPreviewResult(null);
        setPreviewError(null);
        const timer = setTimeout(() => {
            const payload = { leadId, ...buildConvertInputs() };
            api.previewStandardAction(previewEndpoint, payload)
                .then((result) => {
                    if (!controller.signal.aborted) {
                        setServerPreviewResult(result);
                    }
                })
                .catch((err: unknown) => {
                    if (!controller.signal.aborted) {
                        api.warn('[ConvertLeadModal] Failed to load Flow create preview', {
                            previewEndpoint,
                            leadId,
                        }, err);
                        // Clear any previously-rendered preview so the user
                        // never sees stale data from a prior successful fetch.
                        setServerPreviewResult(null);
                        // Show a fixed non-sensitive error message — raw err.message
                        // is intentionally not surfaced to prevent leaking backend details.
                        setPreviewError('Preview unavailable. Try again later.');
                    }
                });
        }, 300);
        return () => {
            clearTimeout(timer);
            controller.abort();
        };
    }, [
        api,
        isOpen,
        previewEndpoint,
        leadId,
        previewReady,
        buildConvertInputs,
    ]);

    // Keep ref in sync so the metadata-fetch effect can read current schemas
    // without taking it as a dependency (avoids infinite loop).
    useEffect(() => {
        previewSchemasRef.current = previewSchemas;
    }, [previewSchemas]);

    // Fetch describe metadata for any new object names in the preview result.
    // Runs after serverPreviewResult changes; cancellable on cleanup.
    useEffect(() => {
        if (!serverPreviewResult) return;
        const objects = new Set<string>();
        if (serverPreviewResult.parentPreview?.object) {
            objects.add(serverPreviewResult.parentPreview.object);
        }
        for (const c of serverPreviewResult.childPreview ?? []) {
            if (c.object) objects.add(c.object);
        }
        const missing = [...objects].filter(o => !(o in previewSchemasRef.current));
        if (missing.length === 0) return;
        let cancelled = false;
        (async () => {
            const updates: Record<string, CrmConvertLeadObjectMetadata | null> = {};
            for (const obj of missing) {
                try {
                    const result = await api.getSchema(obj);
                    updates[obj] = result.schema ?? null;
                } catch (e) {
                    api.warn('[ConvertLeadModal] preview describe failed', { object: obj }, e);
                    updates[obj] = null;
                }
            }
            if (!cancelled) setPreviewSchemas(prev => ({ ...prev, ...updates }));
        })();
        return () => { cancelled = true; };
    }, [api, serverPreviewResult]);

    // Returns the human-readable label for a field, falling back to the API name.
    const fieldLabel = (objectName: string, fieldName: string): string => {
        const schema = previewSchemas[objectName];
        const field = schema?.fields?.find(f => f.name === fieldName);
        return field?.label || fieldName;
    };

    // Returns the human-readable label for an object, falling back to the API name.
    const objectLabel = (objectName: string): string =>
        previewSchemas[objectName]?.label || objectName;

    const handleConvert = async () => {
        if (!actionEndpoint) {
            setError('Action endpoint is not declared by action metadata');
            return;
        }
        if (metadataError) {
            setError(metadataError);
            return;
        }
        if (accountRequiresLocalValue && !accountId) {
            setError('Account is required');
            return;
        }
        if (accountCreatePermissionBlocks) {
            setError('Account create path is not available for this user');
            return;
        }
        if (statusRequiresLocalValue && !convertedStatus) {
            setError('Converted Status is required');
            return;
        }
        if (contactCreatePermissionBlocks) {
            setError('Contact create path is not available for this user');
            return;
        }
        if (contactCreateMissingRequired) {
            setError('Contact required fields are missing');
            return;
        }
        if (contactReuseRequiresLocalValue) {
            setError('Contact is required when choosing an existing Contact');
            return;
        }
        if (opportunityCreatePermissionBlocks) {
            setError('Opportunity create path is not available for this user');
            return;
        }
        if (opportunityCreateMissingRequired) {
            setError('Opportunity required fields are missing');
            return;
        }
        if (opportunityReuseRequiresLocalValue) {
            setError('Opportunity is required when choosing an existing Opportunity');
            return;
        }

        setLoading(true);
        setError(null);
        try {
            const options = buildConvertInputs();

            const response = await api.executeStandardAction(actionEndpoint, [{
                leadId: record.Id,
                ...options,
            }]);
            setLoading(false);
            for (const output of action.outputs || []) {
                const recordId = response[output.name];
                if (recordId && output.referenceTo) {
                    host.navigateToRecord(output.referenceTo, String(recordId));
                    break;
                }
            }
            host.refreshRecord();
            onClose();
        } catch (err: unknown) {
            const message = err instanceof Error ? err.message : 'An unexpected error occurred';
            setError(message);
            setLoading(false);
        }
    };

    const renderCreateInputs = (inputs: CrmConvertLeadActionInput[], disabled = false) => {
        if (inputs.length === 0) {
            return null;
        }
        return (
            <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                {inputs.map(input => {
                    const required = createInputShowsRequired(input);
                    const inputId = `convert-lead-${input.name}`;
                    return (
                        <div key={input.name}>
                            <label htmlFor={inputId} className="block text-sm font-medium text-gray-700 mb-1">
                                {createInputLabel(input)}{required ? ' *' : ''}
                            </label>
                            <input
                                id={inputId}
                                type="text"
                                disabled={disabled}
                                value={createInputValue(input.name)}
                                onChange={(e) => setCreateValue(input.name, e.target.value)}
                                aria-invalid={!disabled && createInputNeedsValue(input)}
                                className={[
                                    'w-full px-3 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500',
                                    disabled ? 'cursor-not-allowed bg-gray-50 text-gray-500' : '',
                                    createInputNeedsValue(input) ? 'border-red-300' : 'border-gray-300',
                                ].join(' ')}
                            />
                        </div>
                    );
                })}
            </div>
        );
    };

    return (
        <BaseModal
            isOpen={isOpen}
            onClose={loading ? () => {} : onClose}
            title="Convert Lead"
            icon={RefreshCw}
            iconClassName="text-blue-600"
            iconBgClassName="bg-blue-100"
            headerClassName="bg-blue-50 border-b border-gray-100"
            maxWidth="lg"
            footer={
                <div className="flex justify-end gap-3">
                    <Button variant="ghost" onClick={onClose} disabled={loading}>
                        Cancel
                    </Button>
                    <Button variant="primary" onClick={handleConvert} loading={loading} disabled={convertDisabled}>
                        Convert
                    </Button>
                </div>
            }
        >
            <div className="p-6 space-y-5">
                <>
                        <p className="text-gray-600">
                            {`Convert `}<strong>{leadName}</strong>{` into an Account, Contact${doNotCreateOpportunity ? '.' : ', and Opportunity.'}`}
                        </p>

                        {campaignAttributionPreview && (
                            <section className="rounded-xl border border-emerald-200 bg-emerald-50/60 p-4 space-y-3">
                                <div className="space-y-1">
                                    <h3 className="text-sm font-semibold text-emerald-900">
                                        {campaignAttributionPreview.title}
                                    </h3>
                                    {campaignAttributionPreview.summary && (
                                        <p className="text-sm text-emerald-800">
                                            {campaignAttributionPreview.summary}
                                        </p>
                                    )}
                                </div>

                                {campaignAttributionPreview.rows.length > 0 && (
                                    <dl className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                                        {campaignAttributionPreview.rows.map((row) => (
                                            <div key={`${row.label}:${row.value}`} className="rounded-lg bg-white/80 px-3 py-2">
                                                <dt className="text-xs font-medium uppercase tracking-wide text-emerald-700">
                                                    {row.label}
                                                </dt>
                                                <dd className="mt-1 text-sm font-medium text-emerald-950">
                                                    {row.value}
                                                </dd>
                                            </div>
                                        ))}
                                    </dl>
                                )}

                                {campaignAttributionPreview.warnings.length > 0 && (
                                    <div className="space-y-2">
                                        {campaignAttributionPreview.warnings.map((warning) => (
                                            <div key={warning} className="flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900">
                                                <AlertCircle className="mt-0.5 h-4 w-4 flex-shrink-0" />
                                                <p>{warning}</p>
                                            </div>
                                        ))}
                                    </div>
                                )}
                            </section>
                        )}

                        {serverPreviewResult?.isSuccess && serverPreviewResult.parentPreview && (
                            <section
                                aria-label="Flow create preview"
                                className="rounded-xl border border-blue-200 bg-blue-50/60 p-4 space-y-3"
                            >
                                <h3 className="text-sm font-semibold text-blue-900">
                                    {`Preview: ${objectLabel(serverPreviewResult.parentPreview.object)}`}
                                </h3>
                                {Object.entries(serverPreviewResult.parentPreview.fields).filter(([key, value]) => {
                                    if (key === 'Id') return false;
                                    if (typeof value === 'string' && value.startsWith('preview-')) return false;
                                    return true;
                                }).length > 0 && (
                                    <dl className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                                        {Object.entries(serverPreviewResult.parentPreview.fields)
                                            .filter(([key, value]) => {
                                                if (key === 'Id') return false;
                                                if (typeof value === 'string' && value.startsWith('preview-')) return false;
                                                return true;
                                            })
                                            .map(([field, value]) => (
                                                <div key={field} className="rounded-lg bg-white/80 px-3 py-2">
                                                    <dt className="text-xs font-medium uppercase tracking-wide text-blue-700">
                                                        {fieldLabel(serverPreviewResult.parentPreview!.object, field)}
                                                    </dt>
                                                    <dd className="mt-1 text-sm font-medium text-blue-950">
                                                        {String(value ?? '')}
                                                    </dd>
                                                </div>
                                            ))}
                                    </dl>
                                )}
                                {serverPreviewResult.childPreview && serverPreviewResult.childPreview.length > 0 && (
                                    <div className="space-y-1">
                                        <p className="text-xs font-medium text-blue-700 uppercase tracking-wide">
                                            Related Records
                                        </p>
                                        <ul className="space-y-1">
                                            {serverPreviewResult.childPreview.map((child: CrmConvertLeadChildPreview) => (
                                                <li
                                                    key={child.object}
                                                    className="text-sm text-blue-800"
                                                >
                                                    {`${objectLabel(child.object)}: ${child.count} record${child.count === 1 ? '' : 's'}`}
                                                </li>
                                            ))}
                                        </ul>
                                    </div>
                                )}
                            </section>
                        )}

                        {previewError && (
                            <div
                                role="status"
                                aria-live="polite"
                                className="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-700"
                            >
                                Preview unavailable. Try again later.
                            </div>
                        )}

                        {showConvertedStatus && (
                            <div>
                                <label className="block text-sm font-medium text-gray-700 mb-1">
                                    Converted Status{statusInputRequired ? ' *' : ''}
                                </label>
                                {statusOptions.length > 0 || convertedStatusRequiredPicklistTag ? (
                                    <select
                                        value={convertedStatus}
                                        onChange={(e) => setConvertedStatus(e.target.value)}
                                        className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                                    >
                                        <option value="">Select status</option>
                                        {statusOptions.map(opt => (
                                            <option key={opt.value} value={opt.value}>{opt.label}</option>
                                        ))}
                                    </select>
                                ) : (
                                    <input
                                        type="text"
                                        value={convertedStatus}
                                        onChange={(e) => setConvertedStatus(e.target.value)}
                                        className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
                                    />
                                )}
                            </div>
                        )}

                        {hasUsableInput('accountId') && accountTarget && (
                            <div>
                                <div className="mb-1 flex items-center justify-between gap-3">
                                    <label className="block text-sm font-medium text-gray-700">
                                        {accountInputLabel}{(accountInputRequired || accountRequiresLocalValue) ? ' *' : ''}
                                    </label>
                                    {!accountCreateDenied && (
                                        <Button
                                            type="button"
                                            variant="ghost"
                                            size="sm"
                                            onClick={handleCreateRelatedRecord}
                                            disabled={loading}
                                        >
                                            Create {accountInputLabel}
                                        </Button>
                                    )}
                                </div>
                                <LookupComponent
                                    ObjectApiName={accountTarget}
                                    value={accountId}
                                    onChange={(value) => {
                                        suppressContactAutoMatchRef.current = false;
                                        setAccountId(value);
                                    }}
                                    placeholder="Search accounts"
                                    error={accountRequiresLocalValue && !accountId}
                                    disabled={loading}
                                />
                            </div>
                        )}

                        {(canCreateContact || canReuseContact) && (
                            <div className="space-y-3">
                                <label className="block text-sm font-medium text-gray-700">Contact</label>
                                <div
                                    className={`grid ${canCreateContact && canReuseContact ? 'grid-cols-2' : 'grid-cols-1'} gap-1 rounded-lg border border-gray-200 bg-gray-50 p-1`}
                                    role="group"
                                    aria-label="Contact conversion mode"
                                >
                                    {canCreateContact && (
                                        <button
                                            type="button"
                                            className={modeButtonClass(contactSelection === 'create', dependentControlsDisabled)}
                                            aria-pressed={contactSelection === 'create'}
                                            disabled={dependentControlsDisabled}
                                            onClick={() => {
                                                suppressContactAutoMatchRef.current = true;
                                                setContactSelection('create');
                                            }}
                                        >
                                            Create New
                                        </button>
                                    )}
                                    {canReuseContact && (
                                        <button
                                            type="button"
                                            className={modeButtonClass(contactSelection === 'reuse', dependentControlsDisabled)}
                                            aria-pressed={contactSelection === 'reuse'}
                                            disabled={dependentControlsDisabled}
                                            onClick={() => setContactSelection('reuse')}
                                        >
                                            Choose Existing
                                        </button>
                                    )}
                                </div>
                                {contactSelection === 'reuse' && canReuseContact && (
                                    <LookupComponent
                                        ObjectApiName={contactTarget}
                                        value={contactId}
                                        onChange={(value) => {
                                            suppressContactAutoMatchRef.current = true;
                                            setContactId(value);
                                        }}
                                        placeholder="Search contacts"
                                        error={contactReuseRequiresLocalValue}
                                        disabled={dependentControlsDisabled}
                                    />
                                )}
                                {contactSelection === 'create' && canCreateContact && (
                                    renderCreateInputs(contactCreateInputs, dependentControlsDisabled)
                                )}
                            </div>
                        )}

                        {hasUsableInput('overwriteLeadSource') && contactId && (
                            <label className="flex items-center gap-3 cursor-pointer">
                                <input
                                    type="checkbox"
                                    checked={overwriteLeadSource}
                                    onChange={(e) => setOverwriteLeadSource(e.target.checked)}
                                    className="w-4 h-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
                                />
                                <span className="text-sm text-gray-700">Overwrite Contact Lead Source</span>
                            </label>
                        )}

                        {(canCreateOpportunity || canReuseOpportunity || canSkipOpportunity) && (
                            <div className="space-y-3">
                                <label className="block text-sm font-medium text-gray-700">Opportunity</label>
                                <div
                                    className={`grid ${opportunityChoiceGridClass} gap-1 rounded-lg border border-gray-200 bg-gray-50 p-1`}
                                    role="group"
                                    aria-label="Opportunity conversion mode"
                                >
                                    {canCreateOpportunity && (
                                        <button
                                            type="button"
                                            className={modeButtonClass(opportunitySelection === 'create', dependentControlsDisabled)}
                                            aria-pressed={opportunitySelection === 'create'}
                                            disabled={dependentControlsDisabled}
                                            onClick={() => setOpportunitySelection('create')}
                                        >
                                            Create New
                                        </button>
                                    )}
                                    {canReuseOpportunity && (
                                        <button
                                            type="button"
                                            className={modeButtonClass(opportunitySelection === 'reuse', dependentControlsDisabled)}
                                            aria-pressed={opportunitySelection === 'reuse'}
                                            disabled={dependentControlsDisabled}
                                            onClick={() => setOpportunitySelection('reuse')}
                                        >
                                            Choose Existing
                                        </button>
                                    )}
                                    {canSkipOpportunity && (
                                        <button
                                            type="button"
                                            className={modeButtonClass(opportunitySelection === 'skip', dependentControlsDisabled)}
                                            aria-pressed={opportunitySelection === 'skip'}
                                            disabled={dependentControlsDisabled}
                                            onClick={() => setOpportunitySelection('skip')}
                                        >
                                            Do Not Create
                                        </button>
                                    )}
                                </div>

                                {opportunitySelection === 'reuse' && canReuseOpportunity && (
                                    <LookupComponent
                                        ObjectApiName={opportunityTarget}
                                        value={opportunityId}
                                        onChange={(value) => setOpportunityId(value)}
                                        placeholder="Search opportunities"
                                        error={opportunityReuseRequiresLocalValue}
                                        disabled={dependentControlsDisabled}
                                    />
                                )}

                                {opportunitySelection === 'create' && canCreateOpportunity && (
                                    renderCreateInputs(opportunityCreateInputs, dependentControlsDisabled)
                                )}
                            </div>
                        )}

                        {hasUsableInput('ownerId') && ownerTarget && (
                            <div>
                                <label className="block text-sm font-medium text-gray-700 mb-1">Owner</label>
                                <LookupComponent
                                    ObjectApiName={ownerTarget}
                                    value={ownerId}
                                    onChange={(value) => setOwnerId(value)}
                                    placeholder="Search users"
                                />
                            </div>
                        )}

                        {(metadataError || error) && (
                            <div className="flex items-start gap-3 text-red-700 bg-red-50 p-4 rounded-lg">
                                <AlertCircle className="w-5 h-5 flex-shrink-0 mt-0.5" />
                                <p className="text-sm">{error || metadataError}</p>
                            </div>
                        )}
                </>
            </div>
        </BaseModal>
    );
};
