// ── Social Login Providers ─────────────────────────────────────────
const socialProviderMeta = {
    google: {
        name: 'Google', icon: 'bi-google', color: '#4285f4', credential: 'OpenID Connect',
        docs: 'https://developers.google.com/identity/openid-connect/openid-connect', requirement: 'Client ID + secret'
    },
    facebook: {
        name: 'Facebook', icon: 'bi-facebook', color: '#1877f2', credential: 'Meta OAuth 2.0',
        docs: 'https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/', requirement: 'App ID + secret'
    },
    apple: {
        name: 'Apple', icon: 'bi-apple', color: '#111827', credential: 'Sign in with Apple',
        docs: 'https://developer.apple.com/documentation/signinwithapple/configuring-your-webpage-for-sign-in-with-apple', requirement: 'Services ID + key'
    },
    microsoft: {
        name: 'Microsoft', icon: 'bi-microsoft', color: '#0067b8', credential: 'Entra ID (OpenID Connect)',
        docs: 'https://learn.microsoft.com/entra/identity-platform/quickstart-register-app', requirement: 'Client ID + secret'
    },
    github: {
        name: 'GitHub', icon: 'bi-github', color: '#24292f', credential: 'GitHub OAuth 2.0',
        docs: 'https://docs.github.com/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app', requirement: 'Client ID + secret'
    },
    linkedin: {
        name: 'LinkedIn', icon: 'bi-linkedin', color: '#0a66c2', credential: 'Sign In with LinkedIn (OIDC)',
        docs: 'https://learn.microsoft.com/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2', requirement: 'Client ID + secret'
    }
};

// Rendered order — mirrors SocialAuthBuilder::PROVIDERS.
const socialProviderOrder = ['google', 'microsoft', 'apple', 'facebook', 'github', 'linkedin'];

// Which credentials each provider cannot work without (mirrors the builder).
const socialRequired = {
    google: ['client_id', 'client_secret'],
    microsoft: ['client_id', 'client_secret'],
    apple: ['services_id', 'team_id', 'key_id', 'private_key'],
    facebook: ['app_id', 'app_secret'],
    github: ['client_id', 'client_secret'],
    linkedin: ['client_id', 'client_secret']
};

// Callback URL each provider console must whitelist, filled in from the
// project's configured app URL.
let socialCallbackBase = '';
let socialLinkedCounts = {};

function socialCallbackUrl(id) {
    const path = `/generated/auth/social/${id}/callback.php`;
    return socialCallbackBase ? `${socialCallbackBase}${path}` : path;
}

function socialCallbackRow(id) {
    const url = socialCallbackUrl(id);
    const known = Boolean(socialCallbackBase);
    return `<div class="social-field is-wide social-callback">
        <label class="form-label"><span>Callback URL to whitelist${socialHelp('Paste this exact URL into the provider console. It must match character for character, including https and any subdirectory.')}</span></label>
        <div class="social-callback-row">
            <code class="social-callback-url" data-callback="${socialEscape(url)}">${socialEscape(url)}</code>
            <button type="button" class="btn btn-sm btn-outline-secondary social-copy" data-copy="${socialEscape(url)}"
                    ${socialTip('Copy this callback URL')}><i class="bi bi-clipboard"></i></button>
        </div>
        ${known ? '' : '<small class="social-callback-warn"><i class="bi bi-exclamation-triangle"></i> Set your app URL in Output settings to get the full address — the path above is relative.</small>'}
    </div>`;
}

/**
 * A provider that is switched ON but missing credentials is silently dropped by
 * the build — the button simply never appears on the sign-in page, with the
 * explanation buried in the build log. Say it here instead, where it is fixable.
 */
function socialUpdateStatusBanner() {
    const host = document.getElementById('socialBuildStatus');
    if (!host) return;
    const rows = [];
    socialProviderOrder.forEach(id => {
        const card = document.querySelector(`.social-provider-card[data-provider="${id}"]`);
        if (!card) return;
        const on = card.querySelector('.social-provider-toggle')?.checked;
        if (!on) return;
        const cfg = socialReadCard(id);
        const status = socialReadiness(id, cfg);
        rows.push({ id, ready: status.ready, missing: status.missing });
    });
    const ready = rows.filter(r => r.ready);
    const broken = rows.filter(r => !r.ready);
    const master = document.getElementById('socialAuthEnabled')?.checked;

    if (!rows.length) {
        host.innerHTML = `<div class="social-build-status is-idle"><i class="bi bi-info-circle"></i>
            <span>No providers are switched on yet, so no social buttons will be built.</span></div>`;
        return;
    }
    host.innerHTML = `
        ${!master ? `<div class="social-build-status is-warn"><i class="bi bi-toggle-off"></i>
            <span><strong>Social authentication is switched off.</strong> Nothing is built until the master switch is on.</span></div>` : ''}
        ${broken.length ? `<div class="social-build-status is-warn">
            <i class="bi bi-exclamation-triangle-fill"></i>
            <span><strong>${broken.length} provider${broken.length === 1 ? '' : 's'} switched on but incomplete</strong> —
            ${broken.length === 1 ? 'it' : 'they'} will <em>not</em> appear on the sign-in page until the missing credentials are filled in:
            <ul>${broken.map(b => `<li><strong>${socialProviderMeta[b.id].name}</strong> — missing ${b.missing.join(', ')}</li>`).join('')}</ul></span>
        </div>` : ''}
        ${ready.length ? `<div class="social-build-status is-ok"><i class="bi bi-check-circle-fill"></i>
            <span><strong>${ready.length} provider${ready.length === 1 ? '' : 's'} will be built:</strong>
            ${ready.map(r => socialProviderMeta[r.id].name).join(', ')}. Rebuild the application to publish the change.</span></div>` : ''}`;
}

/** Update one card's Ready/Incomplete pill from its current (unsaved) fields. */
function socialRefreshCardPill(id) {
    const card = document.querySelector(`.social-provider-card[data-provider="${id}"]`);
    const pill = card?.querySelector('.social-ready');
    if (!pill) return;
    const status = socialReadiness(id, socialReadCard(id));
    pill.classList.toggle('is-ready', status.ready);
    pill.classList.toggle('is-incomplete', !status.ready);
    pill.innerHTML = `<i class="bi ${status.ready ? 'bi-check-circle-fill' : 'bi-exclamation-circle-fill'}"></i> ${status.ready ? 'Ready' : 'Incomplete'}`;
}

/** Read a card's current field values, so the banner reflects unsaved edits. */
function socialReadCard(id) {
    const cap = id.charAt(0).toUpperCase() + id.slice(1);
    const v = suffix => document.getElementById(`social${cap}${suffix}`)?.value.trim() || '';
    const card = document.querySelector(`.social-provider-card[data-provider="${id}"]`);
    const savedSecret = Boolean(card?.querySelector('.social-secret-saved'));
    switch (id) {
        case 'google':    return { client_id: v('ClientId'), client_secret: v('Secret'), has_client_secret: savedSecret };
        case 'microsoft': return { client_id: v('ClientId'), client_secret: v('Secret'), has_client_secret: savedSecret };
        case 'github':    return { client_id: v('ClientId'), client_secret: v('Secret'), has_client_secret: savedSecret };
        case 'linkedin':  return { client_id: v('ClientId'), client_secret: v('Secret'), has_client_secret: savedSecret };
        case 'facebook':  return { app_id: v('AppId'), app_secret: v('Secret'), has_app_secret: savedSecret };
        case 'apple':     return { services_id: v('ServicesId'), team_id: v('TeamId'), key_id: v('KeyId'),
                                   private_key: v('PrivateKey'), has_private_key: savedSecret };
        default: return {};
    }
}

/** Ready / incomplete, computed from the same required list the build uses. */
function socialReadiness(id, config) {
    const missing = (socialRequired[id] || []).filter(key => {
        if (key === 'client_secret' && config.has_client_secret) return false;
        if (key === 'app_secret' && config.has_app_secret) return false;
        if (key === 'private_key' && config.has_private_key) return false;
        return !String(config[key] ?? '').trim();
    });
    return { ready: missing.length === 0, missing };
}

function socialEscape(value) {
    return String(value ?? '').replace(/[&<>"']/g, char => ({
        '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;'
    }[char]));
}

function socialTip(text, placement = 'top') {
    return `data-bs-toggle="tooltip" data-bs-placement="${placement}" data-bs-title="${socialEscape(text)}"`;
}

function socialHelp(text) {
    return `<span class="social-help" tabindex="0" role="img" aria-label="Help: ${socialEscape(text)}" ${socialTip(text)}><i class="bi bi-question-circle"></i></span>`;
}

function socialField(id, label, value = '', options = {}) {
    const type = options.secret ? 'password' : 'text';
    const badge = options.saved ? '<span class="social-secret-saved"><i class="bi bi-check-circle-fill"></i> Saved</span>' : '';
    return `<div class="social-field ${options.wide ? 'is-wide' : ''}">
        <label class="form-label" for="${id}"><span>${label}${options.help ? socialHelp(options.help) : ''}</span>${badge}</label>
        <input class="form-control form-control-sm" id="${id}" type="${type}" value="${socialEscape(value)}" placeholder="${socialEscape(options.placeholder || '')}" autocomplete="off">
    </div>`;
}

function socialProviderCard(id, config) {
    const meta = socialProviderMeta[id];
    const fields = id === 'microsoft' ? `
        ${socialField('socialMicrosoftClientId', 'Application (client) ID', config.client_id, { placeholder: '00000000-0000-0000-0000-000000000000', help: 'Application (client) ID from the Entra app registration.' })}
        ${socialField('socialMicrosoftSecret', 'Client secret', '', { secret: true, saved: config.has_client_secret, placeholder: config.has_client_secret ? 'Keep saved secret' : 'Required', help: 'Client secret VALUE (not the secret ID). Entra shows it only once.' })}
        ${socialField('socialMicrosoftTenant', 'Tenant', config.tenant || 'common', { placeholder: 'common', help: 'common = work, school and personal accounts. organizations = any company. consumers = personal only. Or paste a tenant GUID to allow ONE company only.' })}
        ${socialField('socialMicrosoftRedirect', 'Redirect URI override', config.redirect_uri, { wide: true, placeholder: 'Leave blank to use the callback URL below', help: 'Only needed when the app is reached on a different host than it generates for itself.' })}` : id === 'github' ? `
        ${socialField('socialGithubClientId', 'Client ID', config.client_id, { placeholder: 'Iv1.…', help: 'Client ID of the GitHub OAuth app.' })}
        ${socialField('socialGithubSecret', 'Client secret', '', { secret: true, saved: config.has_client_secret, placeholder: config.has_client_secret ? 'Keep saved secret' : 'Required', help: 'Generated in the OAuth app settings and shown once.' })}
        ${socialField('socialGithubRedirect', 'Authorization callback URL override', config.redirect_uri, { wide: true, placeholder: 'Leave blank to use the callback URL below', help: 'GitHub calls this the “Authorization callback URL”. It must match exactly.' })}` : id === 'linkedin' ? `
        ${socialField('socialLinkedinClientId', 'Client ID', config.client_id, { placeholder: 'LinkedIn app client ID', help: 'From the Auth tab of your LinkedIn app.' })}
        ${socialField('socialLinkedinSecret', 'Client secret', '', { secret: true, saved: config.has_client_secret, placeholder: config.has_client_secret ? 'Keep saved secret' : 'Required', help: 'From the Auth tab. The app also needs the “Sign In with LinkedIn using OpenID Connect” product enabled.' })}
        ${socialField('socialLinkedinRedirect', 'Redirect URL override', config.redirect_uri, { wide: true, placeholder: 'Leave blank to use the callback URL below', help: 'Add this under Authorized redirect URLs for your app.' })}` : id === 'google' ? `
        ${socialField('socialGoogleClientId', 'Client ID', config.client_id, { placeholder: '…apps.googleusercontent.com', help: 'OAuth Web client ID from Google Cloud Console.' })}
        ${socialField('socialGoogleSecret', 'Client secret', '', { secret: true, saved: config.has_client_secret, placeholder: config.has_client_secret ? 'Keep saved secret' : 'Required', help: 'Server-side OAuth secret. It is saved but never returned to this screen.' })}
        ${socialField('socialGoogleRedirect', 'Authorized redirect URI', config.redirect_uri, { wide: true, placeholder: 'https://app.example.com/…/google/callback.php', help: 'Register this exact callback in Google Cloud. Use HTTPS in production.' })}` : id === 'facebook' ? `
        ${socialField('socialFacebookAppId', 'App ID', config.app_id, { placeholder: 'Meta application ID', help: 'Application ID shown in the Meta developer dashboard.' })}
        ${socialField('socialFacebookSecret', 'App secret', '', { secret: true, saved: config.has_app_secret, placeholder: config.has_app_secret ? 'Keep saved secret' : 'Required', help: 'Keep this server-side. Blank retains the previously saved secret.' })}
        ${socialField('socialFacebookVersion', 'Graph version', config.api_version || 'v25.0', { placeholder: 'v25.0', help: 'Versioned Graph API path. Change it when upgrading your Meta app.' })}
        ${socialField('socialFacebookRedirect', 'Valid OAuth redirect URI', config.redirect_uri, { placeholder: 'https://app.example.com/…/facebook/callback.php', help: 'Must exactly match a Valid OAuth Redirect URI in Facebook Login settings.' })}` : `
        ${socialField('socialAppleServicesId', 'Services ID', config.services_id, { placeholder: 'com.example.web', help: 'The Services ID associated with your website and primary App ID.' })}
        ${socialField('socialAppleTeamId', 'Team ID', config.team_id, { placeholder: '10-character Team ID', help: 'Apple Developer team identifier used to sign the client secret.' })}
        ${socialField('socialAppleKeyId', 'Key ID', config.key_id, { placeholder: 'Sign in with Apple key', help: 'Identifier of the Sign in with Apple private key.' })}
        ${socialField('socialAppleRedirect', 'Return URL', config.redirect_uri, { placeholder: 'https://app.example.com/…/apple/callback.php', help: 'Apple requires an exact HTTPS Return URL on a verified domain; localhost and IP addresses are not accepted.' })}
        <div class="social-field is-wide"><label class="form-label" for="socialApplePrivateKey"><span>Private key (.p8)${socialHelp('Paste the private key downloaded once from Apple. Blank retains the saved key. The generated app creates short-lived ES256 client secrets at runtime.')}</span>${config.has_private_key ? '<span class="social-secret-saved"><i class="bi bi-check-circle-fill"></i> Saved</span>' : ''}</label><textarea class="form-control form-control-sm social-private-key" id="socialApplePrivateKey" rows="2" placeholder="${config.has_private_key ? 'Keep saved private key' : '-----BEGIN PRIVATE KEY-----'}"></textarea></div>`;

    const status = socialReadiness(id, config);
    const linked = socialLinkedCounts[id] || 0;
    return `<article class="social-provider-card ${config.enabled ? 'is-enabled' : ''}" data-provider="${id}" style="--provider-color:${meta.color}">
        <header>
            <span class="social-provider-logo"><i class="bi ${meta.icon}"></i></span>
            <div class="social-provider-heading"><strong>${meta.name}</strong><small>${meta.credential}</small></div>
            ${linked ? `<span class="social-linked" ${socialTip(`${linked} user account${linked === 1 ? '' : 's'} already signed in with ${meta.name}.`)}><i class="bi bi-link-45deg"></i> ${linked}</span>` : ''}
            <span class="social-ready ${status.ready ? 'is-ready' : 'is-incomplete'}"
                  ${socialTip(status.ready ? 'All required credentials are present — this provider will be built.' : `Missing: ${status.missing.join(', ')}. The build skips this provider until they are filled in.`)}>
                <i class="bi ${status.ready ? 'bi-check-circle-fill' : 'bi-exclamation-circle-fill'}"></i> ${status.ready ? 'Ready' : 'Incomplete'}
            </span>
            <span class="social-provider-state">${config.enabled ? 'On' : 'Off'}</span>
            <div class="form-check form-switch social-provider-switch">
                <input class="form-check-input social-provider-toggle" id="social${id}Enabled" data-provider="${id}" type="checkbox" ${config.enabled ? 'checked' : ''} ${socialTip(`Show ${meta.name} on enabled generated Login and Register pages.`)}>
                <label class="visually-hidden" for="social${id}Enabled">Enable ${meta.name}</label>
            </div>
        </header>
        <div class="social-provider-body">${fields}${socialCallbackRow(id)}</div>
        <footer><span><i class="bi bi-key"></i> ${meta.requirement}</span><a href="${meta.docs}" target="_blank" rel="noopener noreferrer" ${socialTip(`Open the official ${meta.name} setup documentation.`)}>Setup guide <i class="bi bi-box-arrow-up-right"></i></a></footer>
    </article>`;
}

function socialPolicy(icon, id, title, tooltip, checked) {
    return `<label><input type="checkbox" id="${id}" ${checked ? 'checked' : ''}><span class="social-policy-icon"><i class="bi bi-${icon}"></i></span><strong>${title}</strong>${socialHelp(tooltip)}</label>`;
}

function syncSocialProviderCard(toggle) {
    const card = toggle.closest('.social-provider-card');
    card?.classList.toggle('is-enabled', toggle.checked);
    const state = card?.querySelector('.social-provider-state');
    if (state) state.textContent = toggle.checked ? 'On' : 'Off';
    socialUpdateStatusBanner();
}

function initSocialCopy(root) {
    root.querySelectorAll('.social-copy').forEach(btn => btn.addEventListener('click', async () => {
        const text = btn.getAttribute('data-copy') || '';
        try {
            await navigator.clipboard.writeText(text);
        } catch (e) {
            // clipboard API needs a secure context; fall back to a selection
            const ta = document.createElement('textarea');
            ta.value = text; document.body.appendChild(ta); ta.select();
            try { document.execCommand('copy'); } catch (_) {}
            ta.remove();
        }
        const icon = btn.querySelector('i');
        if (icon) {
            icon.className = 'bi bi-check-lg';
            setTimeout(() => { icon.className = 'bi bi-clipboard'; }, 1400);
        }
        pp.dialog.toast('success', 'Callback URL copied.');
    }));
}

function initSocialAuthTooltips(root) {
    initSocialCopy(root);
    // Recompute readiness as credentials are typed, so the banner is never stale.
    root.querySelectorAll('.social-provider-card input, .social-provider-card textarea')
        .forEach(el => el.addEventListener('input', () => {
            const id = el.closest('.social-provider-card')?.dataset.provider;
            if (id) socialRefreshCardPill(id);
            socialUpdateStatusBanner();
        }));
    root.querySelector('#socialAuthEnabled')?.addEventListener('change', socialUpdateStatusBanner);
    socialUpdateStatusBanner();
    root.querySelectorAll('.social-help').forEach(help => help.addEventListener('click', event => {
        event.preventDefault();
        event.stopPropagation();
    }));
    if (!window.bootstrap?.Tooltip) return;
    root.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(element => {
        window.bootstrap.Tooltip.getInstance(element)?.dispose();
        window.bootstrap.Tooltip.getOrCreateInstance(element, {
            container: 'body', trigger: 'hover focus', customClass: 'security-tooltip', delay: { show: 220, hide: 50 }
        });
    });
}

async function renderSocialAuthSettings() {
    const container = document.getElementById('securityPageContainer');
    container.innerHTML = '<div class="text-center py-5"><div class="spinner-border"></div></div>';
    try {
        const response = await fetch(`${baseUrl}/project/${projectSlug}/security/social-auth`);
        const payload = await response.json();
        if (!payload.success) throw new Error(payload.message || 'Unable to load social login settings.');
        const settings = payload.settings || {};
        const providers = settings.providers || {};
        socialCallbackBase = String(payload.callback_base || '');
        socialLinkedCounts = payload.linked || {};
        const roles = (Array.isArray(payload.roles) ? payload.roles : ['registered'])
            .map(role => String(role || '').trim())
            .filter(role => role && !/admin/i.test(role));
        if (!roles.includes(settings.default_role) && settings.default_role && !/admin/i.test(settings.default_role)) roles.push(settings.default_role);
        const selectedRole = roles.includes(settings.default_role) ? settings.default_role : (roles.includes('registered') ? 'registered' : roles[0]);
        const roleOptions = roles.map(role => `<option value="${socialEscape(role)}" ${role === selectedRole ? 'selected' : ''}>${socialEscape(role)}</option>`).join('');
        container.innerHTML = `<section class="social-auth-settings">
            <div class="social-auth-overview">
                <div><span class="security-page-kicker">OAuth 2.0 + OpenID Connect</span><h3>Connected account sign-in</h3><p>Choose trusted identity providers for generated Login and Register pages.</p></div>
                <label class="social-master-switch"><span class="social-master-icon"><i class="bi bi-person-check"></i></span><span><strong>Social authentication ${socialHelp('Master control for every configured provider. Provider credentials remain saved when this is switched off.')}</strong><small>Master control</small></span><span class="form-check form-switch"><input class="form-check-input" id="socialAuthEnabled" type="checkbox" ${settings.enabled ? 'checked' : ''}></span></label>
            </div>
            ${!window.securitySettings?.db_auth_enabled ? '<div class="alert alert-warning"><i class="bi bi-exclamation-triangle me-1"></i> Enable database authentication first so provider identities can link to local users.</div>' : ''}
            <div id="socialBuildStatus" class="social-build-status-host"></div>
            <div class="social-policy-grid">
                ${socialPolicy('box-arrow-in-right', 'socialAllowLogin', 'Sign in', 'Show enabled providers on the generated Login page.', settings.allow_login)}
                ${socialPolicy('person-plus', 'socialAllowRegistration', 'Sign up', 'Show enabled providers on the generated Register page.', settings.allow_registration)}
                ${socialPolicy('person-check', 'socialAutoCreate', 'Create users', 'Create a local user after a valid provider callback when no linked account exists.', settings.auto_create_users)}
                ${socialPolicy('envelope-check', 'socialLinkEmail', 'Link verified email', 'Link an existing local account only when the provider explicitly verifies the email address.', settings.link_by_verified_email)}
                <label class="social-role"><span class="social-policy-icon"><i class="bi bi-person-gear"></i></span><strong>Default role</strong>${socialHelp('Role assigned only when social authentication creates a new local user. Administrative roles are intentionally unavailable.')}<select class="form-select form-select-sm" id="socialDefaultRole">${roleOptions}</select></label>
            </div>
            <div class="social-provider-grid">
                ${socialProviderOrder.map(id => socialProviderCard(id, providers[id] || {})).join('')}
            </div>
            <div class="social-auth-footer"><div><i class="bi bi-shield-check"></i><span><strong>Secrets stay server-side</strong><small>Blank secret fields retain saved values.</small></span></div><button class="btn btn-primary" id="btnSaveSocialAuth" ${socialTip('Save provider policies and credentials to this project. Rebuild to update the generated application.')}><i class="bi bi-check2-circle me-1"></i> Save providers</button></div>
        </section>`;
        document.querySelectorAll('.social-provider-toggle').forEach(toggle => {
            toggle.addEventListener('change', () => syncSocialProviderCard(toggle));
            syncSocialProviderCard(toggle);
        });
        document.getElementById('btnSaveSocialAuth')?.addEventListener('click', saveSocialAuthSettings);
        initSocialAuthTooltips(container);
    } catch (error) {
        container.innerHTML = `<div class="alert alert-danger">${socialEscape(error.message)}</div>`;
    }
}

async function saveSocialAuthSettings() {
    const button = document.getElementById('btnSaveSocialAuth');
    const value = id => document.getElementById(id)?.value?.trim() || '';
    const settings = {
        enabled: document.getElementById('socialAuthEnabled')?.checked,
        allow_login: document.getElementById('socialAllowLogin')?.checked,
        allow_registration: document.getElementById('socialAllowRegistration')?.checked,
        auto_create_users: document.getElementById('socialAutoCreate')?.checked,
        link_by_verified_email: document.getElementById('socialLinkEmail')?.checked,
        default_role: value('socialDefaultRole') || 'registered',
        providers: {
            google: { enabled: document.getElementById('socialgoogleEnabled')?.checked, client_id: value('socialGoogleClientId'), client_secret: value('socialGoogleSecret'), redirect_uri: value('socialGoogleRedirect') },
            facebook: { enabled: document.getElementById('socialfacebookEnabled')?.checked, app_id: value('socialFacebookAppId'), app_secret: value('socialFacebookSecret'), api_version: value('socialFacebookVersion') || 'v25.0', redirect_uri: value('socialFacebookRedirect') },
            apple: { enabled: document.getElementById('socialappleEnabled')?.checked, services_id: value('socialAppleServicesId'), team_id: value('socialAppleTeamId'), key_id: value('socialAppleKeyId'), private_key: value('socialApplePrivateKey'), redirect_uri: value('socialAppleRedirect') },
            microsoft: { enabled: document.getElementById('socialmicrosoftEnabled')?.checked, client_id: value('socialMicrosoftClientId'), client_secret: value('socialMicrosoftSecret'), tenant: value('socialMicrosoftTenant') || 'common', redirect_uri: value('socialMicrosoftRedirect') },
            github: { enabled: document.getElementById('socialgithubEnabled')?.checked, client_id: value('socialGithubClientId'), client_secret: value('socialGithubSecret'), redirect_uri: value('socialGithubRedirect') },
            linkedin: { enabled: document.getElementById('sociallinkedinEnabled')?.checked, client_id: value('socialLinkedinClientId'), client_secret: value('socialLinkedinSecret'), redirect_uri: value('socialLinkedinRedirect') }
        }
    };
    button?.setAttribute('disabled', 'disabled');
    try {
        const response = await fetch(`${baseUrl}/project/${projectSlug}/security/social-auth`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ settings }) });
        const payload = await response.json();
        if (!payload.success) throw new Error(payload.message || 'Unable to save providers.');
        pp.dialog.toast('success', 'Social login providers saved. Rebuild the application to publish the change.');
        await renderSocialAuthSettings();
    } catch (error) {
        pp.dialog.toast('error', error.message || 'Unable to save providers.');
        button?.removeAttribute('disabled');
    }
}

window.renderSocialAuthSettings = renderSocialAuthSettings;
window.saveSocialAuthSettings = saveSocialAuthSettings;
