/**
 * ConnectionDialog Component
 * Matches design.html - connect panel styling, no Bootstrap markup
 *
 * Registers <success-message-modal> and <error-message-modal> here so this file
 * works even if Razor forgets optional dialog script tags (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('connection-dialog', {
    props: {
        platformType: {
            type: String,
        },
        trigger: {
            type: String,
            default: 'manage'  // 'manage' = full button, 'change' = link only
        }
    },
    data() {
        return {
            connectionStrings: [],
            visible: false,
            /** null | 'new' | connection id — only matching control shows spinner */
            dbTestLoadingKey: null,
            testSuccessVisible: false,
            testSuccessTitle: '',
            testSuccessMessage: '',
            testErrorVisible: false,
            testErrorTitle: '',
            testErrorMessage: '',
            testErrorDetails: '',
            newConnection: {
                Id: 0,
                Name: "",
                ConnectionString: "",
                DefaultMediaHost: "",
                PlatformType: this.platformType
            }
        };
    },
    mounted() {
        this.GetConnections();
    },
    methods: {
        isSavedRowTesting(cs) {
            return this.dbTestLoadingKey !== null && String(this.dbTestLoadingKey) === String(cs.id);
        },
        async GetConnections() {
            try {
                const res = await fetch(`/api/ContentTree/GetAvailableConnectionStrings?platform=${this.platformType}`);
                const json = await res.json();
                this.connectionStrings = json;
            } catch (error) {
                console.error('Error fetching connections:', error);
                if (typeof Helpers !== 'undefined') Helpers.showNotification('Error loading connections', 'error');
            }
        },
        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.invalidateSourceCaches(id, this.platformType);
                } catch (err) {
                    console.error('InvalidateRepositoryCaches', 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();
        },
        blankConnectionForm() {
            return {
                Id: 0,
                Name: "",
                ConnectionString: "",
                DefaultMediaHost: "",
                PlatformType: this.platformType
            };
        },
        loadConnectionForEdit(cs) {
            var id = cs && (cs.id != null ? cs.id : cs.Id);
            this.newConnection = {
                Id: id != null && id > 0 ? id : 0,
                Name: (cs && (cs.name != null ? cs.name : cs.Name)) || '',
                ConnectionString: (cs && (cs.connectionString != null ? cs.connectionString : cs.ConnectionString)) || '',
                DefaultMediaHost:
                    (cs && (cs.defaultMediaHost != null ? cs.defaultMediaHost : cs.DefaultMediaHost)) != null
                        ? String(cs.defaultMediaHost != null ? cs.defaultMediaHost : cs.DefaultMediaHost)
                        : '',
                PlatformType: this.platformType
            };
            var wrap = this.$refs.connectionFormWrap;
            if (wrap && wrap.scrollIntoView) wrap.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        },
        async SaveConnectionString() {
            this.newConnection.PlatformType = this.platformType;
            try {
                await fetch("/api/ContentTree/UpdateConnectionString", {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(this.newConnection)
                });
                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/ContentTree/DeleteConnectionString?id=${connection.id}`);
                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 CopyConnectionString(text, e) {
            if (e) e.stopPropagation();
            const str = (typeof text === 'string' ? text : (text && (text.connectionString || text.ConnectionString))) || '';
            if (!str.trim()) {
                this.$root.$emit('show-toast', { icon: 'bi bi-exclamation-circle', text: 'Nothing to copy' });
                return;
            }
            try {
                await navigator.clipboard.writeText(str);
                this.$root.$emit('show-toast', { icon: 'bi bi-clipboard-check', text: 'Connection string copied to clipboard' });
            } catch (err) {
                console.error('Copy failed:', err);
                this.$root.$emit('show-toast', { icon: 'bi bi-exclamation-circle', text: 'Failed to copy' });
            }
        },
        async TestDatabaseConnection(opts) {
            const connectionId = opts && opts.connectionId != null ? opts.connectionId : null;
            const connectionString = opts && opts.connectionString != null ? String(opts.connectionString).trim() : '';
            const targetKey = connectionId != null ? connectionId : 'new';
            if (connectionId == null && !connectionString) {
                this.showTestOutcomeError('Cannot test', 'Enter a connection string before running the test.', '');
                return;
            }
            if (this.dbTestLoadingKey !== null) return;
            this.dbTestLoadingKey = targetKey;
            try {
                const body = connectionId != null
                    ? { connectionId: connectionId, platformType: this.platformType }
                    : { platformType: this.platformType, connectionString: connectionString };
                const res = await fetch('/api/ContentTree/TestDatabaseConnection', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(body)
                });
                const json = await res.json();
                const ok = json && json.success === true;
                if (ok) {
                    this.showTestOutcomeSuccess(json.title || 'Connection succeeded', json.message || 'Database connection succeeded.');
                } else {
                    this.showTestOutcomeError(json.title || 'Connection failed', json.message || 'Unknown error.', json.details || '');
                }
            } catch (err) {
                console.error('Test connection failed:', err);
                this.showTestOutcomeError(
                    'Connection failed',
                    'The connection to the remote server failed: ' + (err.message || 'Request failed'),
                    err.stack || String(err));
            } finally {
                this.dbTestLoadingKey = null;
            }
        },
        TestNewConnectionString() {
            return this.TestDatabaseConnection({ connectionString: this.newConnection.ConnectionString });
        },
        TestSavedConnection(cs, e) {
            if (e) e.stopPropagation();
            return this.TestDatabaseConnection({ connectionId: cs.id });
        },
        cancelConnectionEdit() {
            this.newConnection = this.blankConnectionForm();
        },
        mediaHostPreview(cs) {
            var h =
                cs &&
                (cs.defaultMediaHost != null
                    ? cs.defaultMediaHost
                    : cs.DefaultMediaHost != null
                      ? cs.DefaultMediaHost
                      : '');
            h = (h && String(h).trim()) || '';
            if (h.length <= 42) return h || '—';
            return h.slice(0, 39) + '…';
        },
    },
    computed: {
        anyDbTestRunning() {
            return this.dbTestLoadingKey !== null;
        },
        isUmbracoPlatform() {
            return String(this.platformType || '')
                .trim()
                .toLowerCase() === 'umbraco';
        },
        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 {{ platformType }} 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 {{ platformType }}</h2>
                        <button type="button" class="connection-dialog-close" @click="CloseModal" aria-label="Close">
                            <i class="bi bi-x-lg"></i>
                        </button>
                    </div>
                    <p>Select an existing connection or add a new one to begin the migration assessment.</p>

                    <div v-if="connectionStrings.length" class="connection-dialog-section">
                        <div class="detail-field-label">Existing Connections</div>
                        <table class="table-dark-custom">
                            <thead>
                                <tr>
                                    <th>Name</th>
                                    <th v-if="isUmbracoPlatform" style="min-width:10rem; color:var(--text-muted); font-weight:500;">Media base URL</th>
                                    <th>Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="cs in connectionStrings" :key="cs.id">
                                    <td style="color:var(--text-primary); font-weight:500;">{{ cs.name }}</td>
                                    <td v-if="isUmbracoPlatform" style="font-size:0.8rem; color:var(--text-secondary); max-width:14rem;" :title="cs.defaultMediaHost || cs.DefaultMediaHost || ''">{{ mediaHostPreview(cs) }}</td>
                                    <td>
                                        <button class="btn-outline-subtle" style="padding:0.3rem 0.6rem; font-size:0.78rem;" @click="TestSavedConnection(cs, $event)" :disabled="anyDbTestRunning" title="Test SQL connection">
                                            <span v-if="isSavedRowTesting(cs)" class="spinner-ring-sm" style="margin:0 0.2rem 0 0;"></span>
                                            <i v-else class="bi bi-lightning-charge"></i> Test
                                        </button>
                                        <button class="btn-outline-subtle" style="margin-left:0.4rem; padding:0.3rem 0.6rem; font-size:0.78rem;" @click="ConnectTo(cs)">
                                            <i class="bi bi-plug"></i> Connect
                                        </button>
                                        <button class="btn-outline-subtle" style="margin-left:0.4rem; padding:0.3rem 0.6rem; font-size:0.78rem;" type="button" @click="loadConnectionForEdit(cs)" :title="isUmbracoPlatform ? 'Edit name, connection string, and media base URL' : 'Edit name and connection string'">
                                            <i class="bi bi-pencil"></i> Edit
                                        </button>
                                        <button class="btn-outline-subtle" style="margin-left:0.4rem; padding:0.3rem 0.6rem; font-size:0.78rem;" @click="CopyConnectionString(cs)" title="Copy connection string">
                                            <i class="bi bi-clipboard"></i> Copy
                                        </button>
                                        <button class="btn-danger-subtle" style="margin-left:0.4rem; padding:0.3rem 0.6rem; font-size:0.78rem;" @click="DeleteConnection(cs)">
                                            <i class="bi bi-trash"></i> Delete
                                        </button>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>

                    <div class="connection-dialog-section" ref="connectionFormWrap">
                        <div class="detail-field-label">{{ editingSavedConnection ? 'Edit connection' : 'Add New Connection' }}</div>
                        <p v-if="isUmbracoPlatform" style="color:var(--text-muted); font-size:0.82rem; margin:0 0 1rem 0; line-height:1.45;">
                            Optional <strong>Media base URL</strong> is the public site origin used first when downloading images and media over HTTP
                            (for example when Umbraco has no domains in <code style="font-size:0.78rem;">umbracoDomain</code>). Example: <code style="font-size:0.78rem;">https://www.example.com</code>
                        </p>
                        <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">Connection String</label>
                            <div style="display:flex; gap:0.4rem; align-items:center;">
                                <input class="form-control-dark" v-model="newConnection.ConnectionString" type="password"
                                    autocomplete="off" style="flex:1;" />
                                <button type="button" class="btn-outline-subtle" style="padding:0.4rem 0.6rem; flex-shrink:0;" title="Copy connection string"
                                    @click="CopyConnectionString(newConnection.ConnectionString)"
                                    :disabled="!newConnection.ConnectionString.trim()">
                                    <i class="bi bi-clipboard"></i> Copy
                                </button>
                            </div>
                        </div>
                        <div v-if="isUmbracoPlatform" style="margin-bottom: 1rem;">
                            <label class="connection-field-label">Media base URL (optional)</label>
                            <input class="form-control-dark" v-model="newConnection.DefaultMediaHost" type="text"
                                placeholder="https://your-live-site.com"
                                style="width:100%;" autocomplete="off" />
                        </div>
                        <div style="display:flex; gap:0.75rem; flex-wrap:wrap; align-items:center;">
                            <button class="btn-accent" @click="SaveConnectionString" :disabled="!newConnection.Name.trim() || !newConnection.ConnectionString.trim()">
                                <i :class="editingSavedConnection ? 'bi bi-check-lg' : 'bi bi-plus-lg'"></i> {{ editingSavedConnection ? 'Update' : 'Save' }}
                            </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="TestNewConnectionString"
                                :disabled="anyDbTestRunning || !newConnection.ConnectionString.trim()">
                                <span v-if="dbTestLoadingKey === 'new'" 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>
    `,
    watch: {
        platformType: {
            handler() {
                this.newConnection = this.blankConnectionForm();
                this.GetConnections();
            }
        }
    },
    beforeDestroy() {
        this.portalOverlayBack();
    }
});
