/**
 * SitefinityConnectionDialog Component
 * Manages Sitefinity target connections (Url + AccessKey).
 * Uses SitefinityConnectivity API, not ContentTree API.
 *
 * Registers <success-message-modal> and <error-message-modal> (guarded singleton).
 */
(function registerChameleonMessageModalsGlobal() {
    if (typeof Vue === 'undefined') return;
    if (window.__chameleonMessageModalsRegistered) return;
    window.__chameleonMessageModalsRegistered = true;

    Vue.component('success-message-modal', {
        props: {
            visible: { type: Boolean, default: false },
            title: { type: String, default: 'Success' },
            message: { type: String, default: '' },
            /** Max content width in px (number) or CSS length string, e.g. 600 or '42rem' */
            dialogWidth: { type: [Number, String], default: 600 }
        },
        computed: {
            panelStyle() {
                var w = this.dialogWidth;
                var str = typeof w === 'string' ? String(w).trim() : '';
                if (str && (str.indexOf('%') !== -1 || str.indexOf('rem') !== -1 || str.indexOf('em') !== -1 || str.indexOf('vw') !== -1 || str.indexOf('px') !== -1)) {
                    return { maxWidth: str, width: '100%' };
                }
                var n = typeof w === 'number' ? w : parseFloat(str.replace(/px\s*$/i, ''));
                if (isNaN(n) || n < 200) n = 600;
                return { maxWidth: 'min(' + n + 'px, calc(100vw - 3.5rem))', width: '100%' };
            }
        },
        methods: {
            close() {
                this.$emit('close');
            },
            onKeydown(e) {
                if (!this.visible) return;
                if (e.key === 'Escape') this.close();
            }
        },
        mounted() {
            document.addEventListener('keydown', this.onKeydown);
        },
        beforeDestroy() {
            document.removeEventListener('keydown', this.onKeydown);
        },
        template: `
        <div v-show="visible" class="message-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="success-modal-title" @click.self="close">
            <div class="message-modal-dialog message-modal-dialog--success" :style="panelStyle" @click.stop>
                <button type="button" class="message-modal-close" @click="close" aria-label="Close">
                    <i class="bi bi-x-lg"></i>
                </button>
                <div class="message-modal-icon-ring message-modal-icon-ring--success">
                    <i class="bi bi-check-circle-fill message-modal-check" aria-hidden="true"></i>
                </div>
                <h3 id="success-modal-title" class="message-modal-title">{{ title }}</h3>
                <p class="message-modal-text">{{ message }}</p>
                <button type="button" class="btn-accent message-modal-btn" @click="close">OK</button>
            </div>
        </div>
        `
    });

    Vue.component('error-message-modal', {
        props: {
            visible: { type: Boolean, default: false },
            title: { type: String, default: 'Error' },
            message: { type: String, default: '' },
            details: { type: String, default: '' },
            dialogWidth: { type: [Number, String], default: 600 }
        },
        computed: {
            panelStyle() {
                var w = this.dialogWidth;
                var str = typeof w === 'string' ? String(w).trim() : '';
                if (str && (str.indexOf('%') !== -1 || str.indexOf('rem') !== -1 || str.indexOf('em') !== -1 || str.indexOf('vw') !== -1 || str.indexOf('px') !== -1)) {
                    return { maxWidth: str, width: '100%' };
                }
                var n = typeof w === 'number' ? w : parseFloat(str.replace(/px\s*$/i, ''));
                if (isNaN(n) || n < 200) n = 600;
                return { maxWidth: 'min(' + n + 'px, calc(100vw - 3.5rem))', width: '100%' };
            }
        },
        methods: {
            close() {
                this.$emit('close');
            },
            onKeydown(e) {
                if (!this.visible) return;
                if (e.key === 'Escape') this.close();
            }
        },
        mounted() {
            document.addEventListener('keydown', this.onKeydown);
        },
        beforeDestroy() {
            document.removeEventListener('keydown', this.onKeydown);
        },
        template: `
        <div v-show="visible" class="message-modal-overlay message-modal-overlay--error" role="alertdialog" aria-modal="true" aria-labelledby="error-modal-title" @click.self="close">
            <div class="message-modal-dialog message-modal-dialog--error" :style="panelStyle" @click.stop>
                <button type="button" class="message-modal-close" @click="close" aria-label="Close">
                    <i class="bi bi-x-lg"></i>
                </button>
                <div class="message-modal-icon-ring message-modal-icon-ring--error">
                    <i class="bi bi-exclamation-triangle-fill message-modal-cross" aria-hidden="true"></i>
                </div>
                <h3 id="error-modal-title" class="message-modal-title">{{ title }}</h3>
                <p class="message-modal-text message-modal-text--error">{{ message }}</p>
                <details v-if="details" class="message-modal-details">
                    <summary class="message-modal-details-summary">Full details</summary>
                    <pre class="message-modal-details-pre">{{ details }}</pre>
                </details>
                <button type="button" class="btn-accent message-modal-btn" @click="close">OK</button>
            </div>
        </div>
        `
    });
})();

Vue.component('sitefinity-connection-dialog', {
    props: {
        trigger: {
            type: String,
            default: 'manage'
        }
    },
    data() {
        return {
            connections: [],
            visible: false,
            sfTestLoading: false,
            testSuccessVisible: false,
            testSuccessTitle: '',
            testSuccessMessage: '',
            testErrorVisible: false,
            testErrorTitle: '',
            testErrorMessage: '',
            testErrorDetails: '',
            newConnection: {
                Id: 0,
                Name: "",
                Url: "",
                AccessKey: ""
            }
        };
    },
    mounted() {
        this.GetConnections();
    },
    methods: {
        normalizeSitefinityUrl(url) {
            var raw = (url || '').trim();
            if (!raw) return '';
            if (!/^https?:\/\//i.test(raw)) raw = 'https://' + raw;
            raw = raw.replace(/\/+$/, '');
            return raw + '/';
        },
        async GetConnections() {
            try {
                const res = await fetch("/api/SitefinityConnectivity/GetAvailableConnectionStrings");
                const json = await res.json();
                this.connections = json;
            } catch (error) {
                console.error('Error fetching Sitefinity connections:', error);
                if (typeof Helpers !== 'undefined') Helpers.showNotification('Error loading connections', 'error');
            }
        },
        blankConnectionForm() {
            return { Id: 0, Name: "", Url: "", AccessKey: "" };
        },
        loadConnectionForEdit(c) {
            var rawUrl = (c && (c.url != null ? c.url : c.Url)) || '';
            rawUrl = String(rawUrl).replace(/\/+$/, '');
            var cid = c ? (c.id != null ? c.id : c.Id) : null;
            var numId = cid != null && cid !== '' ? parseInt(cid, 10) : 0;
            if (isNaN(numId) || numId < 0) numId = 0;
            this.newConnection = {
                Id: numId,
                Name: (c && (c.name != null ? c.name : c.Name)) || '',
                Url: rawUrl,
                AccessKey: (c && (c.accessKey != null ? c.accessKey : c.AccessKey)) || ''
            };
            var wrap = this.$refs.sfConnectionFormWrap;
            if (wrap && wrap.scrollIntoView) wrap.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        },
        cancelConnectionEdit() {
            this.newConnection = this.blankConnectionForm();
        },
        ShowModal() {
            this.visible = true;
            this.resetTestOutcomeModals();
            this.newConnection = this.blankConnectionForm();
            this.GetConnections();
            this.$nextTick(() => this.portalOverlayToBody());
        },
        CloseModal() {
            this.visible = false;
            this.resetTestOutcomeModals();
            this.$nextTick(() => this.portalOverlayBack());
        },
        resetTestOutcomeModals() {
            this.testSuccessVisible = false;
            this.testErrorVisible = false;
            this.testSuccessTitle = '';
            this.testSuccessMessage = '';
            this.testErrorTitle = '';
            this.testErrorMessage = '';
            this.testErrorDetails = '';
        },
        showTestOutcomeSuccess(title, message) {
            this.testSuccessTitle = title;
            this.testSuccessMessage = message;
            this.testSuccessVisible = true;
        },
        showTestOutcomeError(title, message, details) {
            this.testErrorTitle = title;
            this.testErrorMessage = message;
            this.testErrorDetails = details || '';
            this.testErrorVisible = true;
        },
        portalOverlayToBody() {
            var el = this.$refs.overlay;
            if (el && el.parentNode !== document.body) {
                this._overlayOriginalParent = el.parentNode;
                document.body.appendChild(el);
            }
        },
        portalOverlayBack() {
            var el = this.$refs.overlay;
            if (el && this._overlayOriginalParent) {
                this._overlayOriginalParent.appendChild(el);
                this._overlayOriginalParent = null;
            }
        },
        async ConnectTo(connection) {
            var id = connection && (connection.id != null ? connection.id : connection.Id);
            if (id != null && id > 0 && typeof ChameleonCacheRefresh !== 'undefined') {
                try {
                    await ChameleonCacheRefresh.invalidateSitefinityCaches(id);
                } catch (err) {
                    console.error('InvalidateConnectionCaches', err);
                    if (typeof Helpers !== 'undefined')
                        Helpers.showNotification((err && err.message) ? err.message : 'Could not reset server cache', 'error');
                    return;
                }
            }
            this.$emit("connect", connection);
            this.CloseModal();
        },
        async SaveConnection() {
            var name = (this.newConnection.Name || '').trim();
            var url = this.normalizeSitefinityUrl(this.newConnection.Url);
            var key = (this.newConnection.AccessKey || '').trim();
            if (!name || !url || !key) {
                this.showTestOutcomeError('Cannot save', 'Name, URL and Access Key are required.', '');
                return;
            }
            try {
                await fetch("/api/SitefinityConnectivity/UpdateConnectionString", {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        Id: this.newConnection.Id || 0,
                        Name: name,
                        Url: url,
                        AccessKey: key
                    })
                });
                this.GetConnections();
                this.newConnection = this.blankConnectionForm();
                if (typeof Helpers !== 'undefined') Helpers.showNotification('Connection saved successfully', 'success');
            } catch (error) {
                console.error('Error saving connection:', error);
                if (typeof Helpers !== 'undefined') Helpers.showNotification('Error saving connection', 'error');
            }
        },
        async DeleteConnection(connection, e) {
            if (e) e.stopPropagation();
            if (!confirm("Are you sure you want to delete this connection?")) return;
            try {
                await fetch("/api/SitefinityConnectivity/DeleteConnectionString", {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        Id: connection.id,
                        Name: connection.name,
                        Url: connection.url,
                        AccessKey: connection.accessKey
                    })
                });
                this.GetConnections();
                if (typeof Helpers !== 'undefined') Helpers.showNotification('Connection deleted successfully', 'success');
            } catch (error) {
                console.error('Error deleting connection:', error);
                if (typeof Helpers !== 'undefined') Helpers.showNotification('Error deleting connection', 'error');
            }
        },
        async TestSitefinityConnection() {
            var url = this.normalizeSitefinityUrl(this.newConnection.Url);
            var key = (this.newConnection.AccessKey || '').trim();
            if (!url || !key) {
                this.showTestOutcomeError('Cannot test', 'Enter URL and API access key before running the test.', '');
                return;
            }
            if (this.sfTestLoading) return;
            this.sfTestLoading = true;
            try {
                const res = await fetch('/api/SitefinityConnectivity/TestConnection', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ url: url, accessKey: key })
                });
                const json = await res.json();
                var ok = json && json.success === true;
                if (ok) {
                    this.showTestOutcomeSuccess(json.title || 'Connection succeeded', json.message || 'OData reachable.');
                } else {
                    this.showTestOutcomeError(json.title || 'Connection failed', json.message || 'Unknown error.', json.details || '');
                }
            } catch (err) {
                console.error('Test Sitefinity connection failed:', err);
                this.showTestOutcomeError(
                    'Connection failed',
                    'The connection to the remote server failed: ' + (err.message || 'Request failed'),
                    err.stack || String(err));
            } finally {
                this.sfTestLoading = false;
            }
        },
    },
    computed: {
        editingSavedConnection() {
            var id = this.newConnection && this.newConnection.Id;
            return id != null && Number(id) > 0;
        },
    },
    template: `
        <div>
            <success-message-modal
                :visible="testSuccessVisible"
                :title="testSuccessTitle"
                :message="testSuccessMessage"
                @close="testSuccessVisible = false">
            </success-message-modal>
            <error-message-modal
                :visible="testErrorVisible"
                :title="testErrorTitle"
                :message="testErrorMessage"
                :details="testErrorDetails"
                @close="testErrorVisible = false">
            </error-message-modal>

            <button v-if="trigger !== 'change'" type="button" class="connection-trigger" @click="ShowModal">Manage Sitefinity Connections</button>
            <a v-else href="#" class="connection-change-link" @click.prevent="ShowModal">Change</a>

            <div v-show="visible" ref="overlay" class="connection-overlay" @click.self="CloseModal">
                <div class="connect-panel connection-dialog-panel connection-dialog-panel--wide">
                    <div class="connection-dialog-header">
                        <h2>Connect to Sitefinity</h2>
                        <button type="button" class="connection-dialog-close" @click="CloseModal" aria-label="Close">
                            <i class="bi bi-x-lg"></i>
                        </button>
                    </div>
                    <p style="color:var(--text-secondary);">Add a Sitefinity target server. Enter the base URL and API access key for OData calls.</p>

                    <div v-if="connections.length" class="connection-dialog-section">
                        <div class="detail-field-label">Existing Connections</div>
                        <table class="table-dark-custom">
                            <thead>
                                <tr>
                                    <th>Name</th>
                                    <th>URL</th>
                                    <th>Status</th>
                                    <th>Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="c in connections" :key="c.id">
                                    <td style="color:var(--text-primary); font-weight:500;">{{ c.name }}</td>
                                    <td style="color:var(--text-secondary); font-size:0.85rem;">{{ c.url }}</td>
                                    <td>
                                        <span v-if="c.isOffline" class="text-danger">Offline</span>
                                        <span v-else class="text-success">Online</span>
                                    </td>
                                    <td>
                                        <button class="btn-outline-subtle" style="padding:0.3rem 0.6rem; font-size:0.78rem;" @click="ConnectTo(c)">
                                            <i class="bi bi-plug"></i> Connect
                                        </button>
                                        <button type="button" class="btn-outline-subtle" style="margin-left:0.4rem; padding:0.3rem 0.6rem; font-size:0.78rem;" title="Edit name, URL, and access key" @click="loadConnectionForEdit(c)">
                                            <i class="bi bi-pencil"></i> Edit
                                        </button>
                                        <button class="btn-danger-subtle" style="margin-left:0.4rem; padding:0.3rem 0.6rem; font-size:0.78rem;" @click="DeleteConnection(c)">
                                            <i class="bi bi-trash"></i> Delete
                                        </button>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>

                    <div class="connection-dialog-section" ref="sfConnectionFormWrap">
                        <div class="detail-field-label">{{ editingSavedConnection ? 'Edit connection' : 'Add New Connection' }}</div>
                        <div style="margin-bottom: 1rem;">
                            <label class="connection-field-label">Name</label>
                            <input class="form-control-dark" v-model="newConnection.Name" type="text"
                                style="width:100%; font-family:'IBM Plex Sans',sans-serif;" />
                        </div>
                        <div style="margin-bottom: 1rem;">
                            <label class="connection-field-label">URL</label>
                            <input class="form-control-dark" v-model="newConnection.Url" type="text"
                                style="width:100%;" />
                        </div>
                        <div style="margin-bottom: 1rem;">
                            <label class="connection-field-label">Access Key</label>
                            <input class="form-control-dark" v-model="newConnection.AccessKey" type="password"
                                autocomplete="off" style="width:100%;" />
                            <a href="https://webstack.azurewebsites.net/pages/pdf-view?oid=105" target="_blank" rel="noopener" style="font-size:0.8rem; color:var(--accent-bright); margin-top:0.3rem; display:inline-block;">How to get one?</a>
                        </div>
                        <div style="display:flex; gap:0.75rem; flex-wrap:wrap; align-items:center;">
                            <button class="btn-accent" @click="SaveConnection"
                                :disabled="!newConnection.Name.trim() || !newConnection.Url?.trim() || !newConnection.AccessKey?.trim()">
                                <i :class="editingSavedConnection ? 'bi bi-check-lg' : 'bi bi-plus-lg'"></i> {{ editingSavedConnection ? 'Update connection' : 'Save Connection' }}
                            </button>
                            <button v-if="editingSavedConnection" type="button" class="btn-outline-subtle" style="padding:0.45rem 0.75rem; font-size:0.84rem;" @click="cancelConnectionEdit">
                                Cancel edit
                            </button>
                            <button type="button" class="btn-outline-subtle" style="padding:0.45rem 0.75rem; font-size:0.84rem;"
                                @click="TestSitefinityConnection"
                                :disabled="sfTestLoading || !newConnection.Url?.trim() || !newConnection.AccessKey?.trim()">
                                <span v-if="sfTestLoading" class="spinner-ring-sm" style="margin:0 0.35rem 0 0;"></span>
                                <i v-else class="bi bi-lightning-charge"></i> Test Connection
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    `,
    beforeDestroy() {
        this.portalOverlayBack();
    }
});
