import React__default, { useMemo, useCallback, useState } from 'react';
import { deepEqual } from '../../utils/deepEqual.mjs';
import { Button } from '../components/Button.mjs';
import { CopyableText } from '../components/CopyableText.mjs';
import { FlexBox } from '../shared/components/FlexBox.mjs';
import { Input } from '../components/Input.mjs';
import { ListEditor } from '../components/ListEditor.mjs';
import { Modal } from '../components/Modal.mjs';
import { Select } from '../components/Select.mjs';
import { SettingsContainer, useSettingsContainer } from '../components/SettingsContainer.mjs';
import { SettingsList } from '../components/SettingsList.mjs';
import { SettingsListItem } from '../components/SettingsListItem.mjs';
import { SettingsSection } from '../components/SettingsSection.mjs';
import { Typography } from '../components/Typography.mjs';
import { useFormState } from '../utils/useFormState.mjs';
import { useMutateSsoConnection, useDeleteSsoConnectionCert, useMutateSsoConnectionByUrl } from '../utils/useMutateSsoConnection.mjs';
import { useStateSliceSetter } from '../utils/useStateSliceSetter.mjs';
import { DefaultAppDetails } from './AppDetails.mjs';
import { AttributeMappingTable } from './AttributeMappingTable.mjs';
import { getIdpAndConnectionInfo } from './IdpInfo.mjs';
import { samlIdpSelectItems, oidcIdpSelectItems } from './IdpSelect.mjs';
import { useSsoRouterController } from './SSORouter.mjs';
import { StytchSDKAPIError } from '../../../../core/src/public/SDKErrors.mjs';
import { useModalState } from '../shared/components/Modal.mjs';

const certItemRenderer = [
    {
        title: 'Issuer',
        getValue: (item)=>/*#__PURE__*/ React__default.createElement(Typography, {
                variant: "body2"
            }, 'issuer' in item ? item.issuer : 'Pending')
    },
    {
        title: 'Created',
        getValue: (item)=>/*#__PURE__*/ React__default.createElement(Typography, {
                variant: "body2"
            }, 'created_at' in item ? new Date(item.created_at).toLocaleString() : 'Pending')
    },
    {
        title: 'Expires',
        getValue: (item)=>/*#__PURE__*/ React__default.createElement(Typography, {
                variant: "body2"
            }, 'expires_at' in item ? new Date(item.expires_at).toLocaleString() : 'Pending')
    }
];
const certKeyExtractor = (item)=>'certificate_id' in item ? item.certificate_id : 'new-certificate-id-pending';
const CertificateTable = ({ editing, localState, manualConfiguration, remoteState, setLocalState })=>{
    const certificates = useMemo(()=>{
        if (!remoteState) {
            return undefined;
        }
        const remoteCertificates = remoteState;
        if (!editing) {
            return remoteCertificates;
        }
        return [
            ...remoteCertificates.filter((cert)=>!localState.deletedCertificateIds?.includes(cert.certificate_id)),
            ...localState.certificate ? [
                {
                    certificate: localState.certificate,
                    isPending: true
                }
            ] : []
        ];
    }, [
        editing,
        localState,
        remoteState
    ]);
    const viewCertModalProps = useModalState();
    const [viewCertificateContents, setViewCertificateContents] = useState();
    const persistPendingCertificate = useStateSliceSetter(setLocalState, 'certificate');
    const addCertModalProps = useModalState(()=>{
        persistPendingCertificate(pendingCert);
    });
    const [pendingCert, setPendingCert] = useState('');
    const remoteCertificateCount = remoteState?.length ?? 0;
    const remoteCertificatePendingDeletionCount = localState.deletedCertificateIds?.length ?? 0;
    const minimumRequiredCertificates = 1;
    const maximumAllowedCertificates = 5;
    const canDeleteCertificates = remoteCertificateCount - remoteCertificatePendingDeletionCount > minimumRequiredCertificates;
    const canAddCertificate = editing && manualConfiguration && !localState.certificate && remoteCertificateCount - remoteCertificatePendingDeletionCount < maximumAllowedCertificates;
    return /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(Modal, {
        ...viewCertModalProps,
        title: "View x509 Certificate",
        confirmButtonText: "Close",
        noCancelButton: true
    }, /*#__PURE__*/ React__default.createElement(CopyableText, {
        whiteSpace: "pre-wrap"
    }, viewCertificateContents)), /*#__PURE__*/ React__default.createElement(Modal, {
        ...addCertModalProps,
        title: "Add Certificate"
    }, /*#__PURE__*/ React__default.createElement(Input, {
        label: "x509 Certificate",
        multiline: true,
        onChange: (value)=>{
            setPendingCert(value);
        },
        placeholder: "Enter certificate",
        value: pendingCert
    })), /*#__PURE__*/ React__default.createElement(ListEditor, {
        items: certificates ?? [],
        itemRenderer: certItemRenderer,
        rowKeyExtractor: certKeyExtractor,
        onAdd: ()=>{
            setPendingCert('');
            addCertModalProps.open();
        },
        getItemActionProps: (item)=>({
                action: {
                    text: item.isPending ? 'Edit' : 'View',
                    onClick: ()=>{
                        if (item.isPending) {
                            setPendingCert(item.certificate);
                            addCertModalProps.open();
                        } else {
                            setViewCertificateContents(item.certificate);
                            viewCertModalProps.open();
                        }
                    }
                },
                warningAction: editing && (item.isPending || canDeleteCertificates) ? {
                    text: 'Delete',
                    onClick: ()=>{
                        if (item.isPending) {
                            persistPendingCertificate(undefined);
                        } else if ('certificate_id' in item) {
                            setLocalState((state)=>{
                                return {
                                    ...state,
                                    deletedCertificateIds: [
                                        ...state.deletedCertificateIds ?? [],
                                        item.certificate_id
                                    ]
                                };
                            });
                        }
                    }
                } : undefined
            }),
        hideAddButton: !canAddCertificate
    }));
};
const DetailsSectionBody = ({ connection: taggedConnection, localState, remoteState, setLocalState })=>{
    const { editing } = useSettingsContainer();
    const { displayName, identityProvider } = editing ? localState : remoteState;
    const handleDisplayNameChange = useStateSliceSetter(setLocalState, 'displayName');
    const handleIdentityProviderChange = useStateSliceSetter(setLocalState, 'identityProvider');
    const handleMetadataUrlChange = useStateSliceSetter(setLocalState, 'metadataUrl');
    const handleSsoUrlChange = useStateSliceSetter(setLocalState, 'ssoUrl');
    const handleEntityIdChange = useStateSliceSetter(setLocalState, 'entityId');
    const handleClientIdChange = useStateSliceSetter(setLocalState, 'clientId');
    const handleClientSecretChange = useStateSliceSetter(setLocalState, 'clientSecret');
    const handleIssuerChange = useStateSliceSetter(setLocalState, 'issuer');
    const handleIssuerDerivedValueChange = useStateSliceSetter(setLocalState, 'issuerDerivedValue');
    const handleAuthorizationUrlChange = useStateSliceSetter(setLocalState, 'authorizationUrl');
    const handleTokenUrlChange = useStateSliceSetter(setLocalState, 'tokenUrl');
    const handleUserInfoUrlChange = useStateSliceSetter(setLocalState, 'userInfoUrl');
    const handleJwksUrlChange = useStateSliceSetter(setLocalState, 'jwksUrl');
    const { connection, idp, type } = getIdpAndConnectionInfo(taggedConnection);
    const idpRequiresManualConfig = type === 'saml' && idp.metadataUrlLabel === false;
    const manualConfiguration = localState.manualConfiguration || idpRequiresManualConfig;
    const setManualConfiguration = useStateSliceSetter(setLocalState, 'manualConfiguration');
    return /*#__PURE__*/ React__default.createElement(FlexBox, {
        flexDirection: "column",
        gap: 2
    }, /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "Display Name"
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        value: displayName,
        onChange: handleDisplayNameChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, displayName)), connection.connectionType === 'external' && /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "Source Organization ID"
    }, /*#__PURE__*/ React__default.createElement(CopyableText, null, connection.external_organization_id)), /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "Connection ID"
    }, /*#__PURE__*/ React__default.createElement(CopyableText, null, connection.connection_id)), /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "External Connection ID"
    }, /*#__PURE__*/ React__default.createElement(CopyableText, null, connection.external_connection_id))), (type === 'saml' || type === 'oidc') && /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "IdP"
    }, editing ? /*#__PURE__*/ React__default.createElement(Select, {
        width: 360,
        placeholder: "Select",
        selectItems: type === 'saml' ? samlIdpSelectItems : oidcIdpSelectItems,
        value: identityProvider,
        onChange: handleIdentityProviderChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, idp.displayName)), /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "App Values",
        tooltipText: "Copy these App (Service Provider) Values into your IdP."
    }, /*#__PURE__*/ React__default.createElement(SettingsList, null, /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: "Connection ID"
    }, /*#__PURE__*/ React__default.createElement(CopyableText, null, connection.connection_id)), /*#__PURE__*/ React__default.createElement(DefaultAppDetails, {
        connection: connection
    }))), /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: "IdP Values"
    }, /*#__PURE__*/ React__default.createElement(SettingsList, null, type === 'saml' && /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, editing && !manualConfiguration ? /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.metadataUrlLabel
    }, /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: `Enter ${idp.metadataUrlLabel}`,
        value: localState.metadataUrl || '',
        onChange: handleMetadataUrlChange
    })) : /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.idpSsoUrlLabel
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: `Enter ${idp.idpSsoUrlLabel}`,
        value: localState.ssoUrl || '',
        onChange: handleSsoUrlChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, connection.idp_sso_url || '–')), /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.idpEntityIdLabel
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: `Enter ${idp.idpEntityIdLabel}`,
        value: localState.entityId || '',
        onChange: handleEntityIdChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, connection.idp_entity_id || '–'))), /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.x509CertificateLabel
    }, /*#__PURE__*/ React__default.createElement(CertificateTable, {
        editing: editing,
        remoteState: connection.verification_certificates,
        localState: localState,
        setLocalState: setLocalState,
        manualConfiguration: manualConfiguration
    })), editing && !idpRequiresManualConfig && /*#__PURE__*/ React__default.createElement(Button, {
        compact: true,
        variant: "ghost",
        onClick: ()=>{
            setManualConfiguration(!manualConfiguration);
        }
    }, manualConfiguration ? `Configure using ${idp.metadataUrlLabel}` : 'Configure manually')), type === 'oidc' && /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.clientIdLabel
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: `Enter ${idp.clientIdLabel}`,
        value: localState.clientId || '',
        onChange: handleClientIdChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, connection.client_id || '–')), /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.clientSecretLabel
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: `Enter ${idp.clientSecretLabel}`,
        value: localState.clientSecret || '',
        onChange: handleClientSecretChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, connection.client_secret || '–')), idp.issuerDerivedLabel ? /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.issuerDerivedLabel
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: `Enter ${idp.issuerDerivedLabel}`,
        value: localState.issuerDerivedValue || '',
        onChange: handleIssuerDerivedValueChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, idp.extractIssuerFromInput?.(connection.issuer) || '–')) : /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: idp.issuerLabel
    }, editing ? /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: "URL",
        value: localState.issuer || '',
        onChange: handleIssuerChange
    }) : /*#__PURE__*/ React__default.createElement(Typography, {
        variant: "body2"
    }, connection.issuer || '–')), editing && /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, manualConfiguration && /*#__PURE__*/ React__default.createElement(React__default.Fragment, null, /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: "Authorization URL"
    }, /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: "Enter Authorization URL",
        value: localState.authorizationUrl || '',
        onChange: handleAuthorizationUrlChange
    })), /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: "Token URL"
    }, /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: "Enter Token URL",
        value: localState.tokenUrl || '',
        onChange: handleTokenUrlChange
    })), /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: "User info URL"
    }, /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: "Enter User info URL",
        value: localState.userInfoUrl || '',
        onChange: handleUserInfoUrlChange
    })), /*#__PURE__*/ React__default.createElement(SettingsListItem, {
        title: "JWKS URL"
    }, /*#__PURE__*/ React__default.createElement(Input, {
        placeholder: "Enter JWKS URL",
        value: localState.jwksUrl || '',
        onChange: handleJwksUrlChange
    }))), /*#__PURE__*/ React__default.createElement(Button, {
        compact: true,
        variant: "ghost",
        onClick: ()=>{
            setManualConfiguration(!manualConfiguration);
        }
    }, manualConfiguration ? `Configure using ${idp.issuerDerivedLabel ?? idp.issuerLabel}` : 'Configure manually')))))), type === 'saml' && /*#__PURE__*/ React__default.createElement(SettingsSection, {
        title: idp.attributeMappingLabel
    }, /*#__PURE__*/ React__default.createElement(AttributeMappingTable, {
        editing: editing,
        localState: localState,
        remoteState: remoteState,
        setLocalState: setLocalState
    })));
};
const DetailsSection = ({ canUpdateConnection, connection: connectionProp })=>{
    const { idp, connection, type } = getIdpAndConnectionInfo(connectionProp);
    const remoteState = useMemo(()=>({
            displayName: connection.display_name,
            identityProvider: 'identity_provider' in connection ? connection.identity_provider : undefined,
            attributeMapping: 'attribute_mapping' in connection ? connection.attribute_mapping : {},
            manualConfiguration: false,
            authorizationUrl: 'authorization_url' in connection ? connection.authorization_url : undefined,
            clientId: 'client_id' in connection ? connection.client_id : undefined,
            clientSecret: 'client_secret' in connection ? connection.client_secret : undefined,
            entityId: 'idp_entity_id' in connection ? connection.idp_entity_id : undefined,
            issuer: 'issuer' in connection ? connection.issuer : undefined,
            issuerDerivedValue: type === 'oidc' ? idp.extractIssuerFromInput?.(connection.issuer) : undefined,
            jwksUrl: 'jwks_url' in connection ? connection.jwks_url : undefined,
            ssoUrl: 'idp_sso_url' in connection ? connection.idp_sso_url : undefined,
            tokenUrl: 'token_url' in connection ? connection.token_url : undefined,
            userInfoUrl: 'userinfo_url' in connection ? connection.userinfo_url : undefined
        }), [
        connection,
        idp,
        type
    ]);
    const { localState, setLocalState, editing, handleSetEditing } = useFormState({
        remoteState
    });
    const { mutate } = useMutateSsoConnection(type);
    const { mutate: deleteCertificate } = useDeleteSsoConnectionCert();
    const { mutate: mutateByUrl } = useMutateSsoConnectionByUrl();
    const handleSave = useCallback(async ()=>{
        const baseOptions = {
            connection_id: connection.connection_id
        };
        const mutatedProperties = {};
        if (remoteState.displayName !== localState.displayName) {
            mutatedProperties.display_name = localState.displayName;
        }
        if (remoteState.identityProvider !== localState.identityProvider) {
            mutatedProperties.identity_provider = localState.identityProvider;
        }
        const idpRequiresManualConfig = type === 'saml' && idp.metadataUrlLabel === false;
        const isManualConfig = localState.manualConfiguration || idpRequiresManualConfig;
        if (type === 'saml') {
            if (localState.deletedCertificateIds?.length) {
                for (const certificateId of localState.deletedCertificateIds){
                    try {
                        await deleteCertificate({
                            connection_id: connection.connection_id,
                            certificate_id: certificateId
                        });
                    } catch (e) {
                        // If certificate was not found, we can ignore the error since we
                        // were trying to delete it anyway
                        if (e instanceof StytchSDKAPIError && e.error_type === 'sso_verification_key_not_found') {
                            return;
                        }
                        throw e;
                    }
                    // Update local state to reflect that the certificate was deleted, in
                    // case a later operation fails
                    setLocalState((state)=>{
                        return {
                            ...state,
                            deletedCertificateIds: state.deletedCertificateIds?.filter((id)=>id !== certificateId)
                        };
                    });
                }
            }
            if (isManualConfig) {
                if (localState.ssoUrl !== remoteState.ssoUrl) {
                    mutatedProperties.idp_sso_url = localState.ssoUrl;
                }
                if (localState.entityId !== remoteState.entityId) {
                    mutatedProperties.idp_entity_id = localState.entityId;
                }
                if (localState.certificate) {
                    mutatedProperties.x509_certificate = localState.certificate;
                }
            } else if (localState.metadataUrl) {
                await mutateByUrl({
                    connection_id: connection.connection_id,
                    metadata_url: localState.metadataUrl
                });
            }
            if (!deepEqual(remoteState.attributeMapping, localState.attributeMapping)) {
                mutatedProperties.attribute_mapping = localState.attributeMapping;
            }
        } else if (type === 'oidc') {
            if (localState.clientId !== remoteState.clientId) {
                mutatedProperties.client_id = localState.clientId;
            }
            if (localState.clientSecret !== remoteState.clientSecret) {
                mutatedProperties.client_secret = localState.clientSecret;
            }
            if (isManualConfig) {
                if (localState.authorizationUrl !== remoteState.authorizationUrl) {
                    mutatedProperties.authorization_url = localState.authorizationUrl;
                }
                if (localState.tokenUrl !== remoteState.tokenUrl) {
                    mutatedProperties.token_url = localState.tokenUrl;
                }
                if (localState.userInfoUrl !== remoteState.userInfoUrl) {
                    mutatedProperties.userinfo_url = localState.userInfoUrl;
                }
                if (localState.jwksUrl !== remoteState.jwksUrl) {
                    mutatedProperties.jwks_url = localState.jwksUrl;
                }
            }
            const getIssuer = ()=>{
                if (localState.issuerDerivedValue !== undefined) {
                    // If we failed to extract derived value from the remote connection's
                    // issuer, and we the new derived value is empty, leave the field
                    // alone
                    if (!localState.issuerDerivedValue && !remoteState.issuerDerivedValue) {
                        return undefined;
                    }
                    return idp.transformInputToIssuer?.(localState.issuerDerivedValue);
                }
                return localState.issuer;
            };
            const issuer = getIssuer();
            if (issuer !== undefined && issuer !== remoteState.issuer) {
                mutatedProperties.issuer = issuer;
            }
        }
        if (Object.keys(mutatedProperties).length > 0) {
            await mutate({
                ...baseOptions,
                ...mutatedProperties
            });
        }
    }, [
        connection.connection_id,
        deleteCertificate,
        idp,
        localState.attributeMapping,
        localState.authorizationUrl,
        localState.certificate,
        localState.clientId,
        localState.clientSecret,
        localState.deletedCertificateIds,
        localState.displayName,
        localState.entityId,
        localState.identityProvider,
        localState.issuer,
        localState.issuerDerivedValue,
        localState.jwksUrl,
        localState.manualConfiguration,
        localState.metadataUrl,
        localState.ssoUrl,
        localState.tokenUrl,
        localState.userInfoUrl,
        mutate,
        mutateByUrl,
        remoteState.attributeMapping,
        remoteState.authorizationUrl,
        remoteState.clientId,
        remoteState.clientSecret,
        remoteState.displayName,
        remoteState.entityId,
        remoteState.identityProvider,
        remoteState.issuer,
        remoteState.issuerDerivedValue,
        remoteState.jwksUrl,
        remoteState.ssoUrl,
        remoteState.tokenUrl,
        remoteState.userInfoUrl,
        setLocalState,
        type
    ]);
    const { useBlockNavigation } = useSsoRouterController();
    return /*#__PURE__*/ React__default.createElement(SettingsContainer, {
        title: "Details",
        hasCTA: canUpdateConnection,
        onSave: handleSave,
        useBlockNavigation: useBlockNavigation,
        editing: editing,
        setEditing: handleSetEditing
    }, /*#__PURE__*/ React__default.createElement(DetailsSectionBody, {
        connection: connection,
        localState: localState,
        remoteState: remoteState,
        setLocalState: setLocalState
    }));
};

export { DetailsSection };
//# sourceMappingURL=DetailsSection.mjs.map
