import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Alert, Col, Row, Space, Spin, Typography } from 'antd';
import { useEffect, useLayoutEffect, useState } from 'react';
import styled from 'styled-components';
import { usePlaygroundContext } from '../../hooks';
import envVarsDatabaseMap from '../../shared/env-vars-db-map';
import { fetchPoll, fetchWithTimeout } from '../../utils';
import ConnectionTest from './components/ConnectionTest';
import { DatabaseCard, SelectedDatabaseCard } from './components/DatabaseCard';
import DatabaseForm from './components/DatabaseForm';
import { Button } from '../../atoms';
import { FatalError } from '../../components/Error/FatalError';
import { LocalhostTipBox } from './components/LocalhostTipBox';
import { event, playgroundAction } from '../../events';
const { Title, Paragraph } = Typography;
const STATUS = {
    INSTALLING: 'installing',
    INSTALLED: 'installed',
};
const DatabaseCardWrapper = styled.div `
  cursor: pointer;
`;
const Layout = styled.div `
  width: auto;
  min-height: 100vh;
  max-width: 960px;
  padding: 48px 24px;
  margin: 0 auto;
  background-color: #fff;
`;
const databases = envVarsDatabaseMap.reduce((memo, { databases: dbs, settings }) => [
    ...memo,
    ...dbs.map((db) => ({ ...db, settings })),
], []);
async function testConnection(variables) {
    const response = await fetchWithTimeout('/playground/test-connection', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            variables,
        }),
    }, 5 * 1000);
    const { error } = await response.json();
    if (error) {
        throw new Error(error);
    }
}
async function saveConnection(variables) {
    await fetch('playground/env', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            variables,
        }),
    });
}
export function ConnectionWizardPage({ history }) {
    const playgroundContext = usePlaygroundContext();
    const [hostname, setHostname] = useState('');
    const [isLoading, setLoading] = useState(false);
    const [isTestConnectionLoading, setTestConnectionLoading] = useState(false);
    const [testConnectionResult, setTestConnectionResult] = useState(null);
    const [db, selectDatabase] = useState(null);
    const [isDriverInstallationInProgress, setDriverInstallationInProgress] = useState(false);
    const [dependencyName, setDependencyName] = useState(null);
    const [installationError, setInstallationError] = useState(null);
    useEffect(() => {
        playgroundAction('connection_wizard_open');
    }, []);
    useLayoutEffect(() => {
        if (playgroundContext?.dbType && !playgroundContext?.isDocker) {
            selectDatabase(databases.find((currentDb) => currentDb.driver.toLowerCase() === playgroundContext.dbType) || null);
        }
    }, [playgroundContext]);
    useEffect(() => {
        let fetchResult;
        if (isDriverInstallationInProgress && db) {
            fetchResult = fetchPoll(`/playground/driver?driver=${db.driver}`, 1000, async ({ response, cancel }) => {
                const { status, error } = await response.json();
                if (response.ok && status === STATUS.INSTALLED) {
                    cancel();
                    setDriverInstallationInProgress(false);
                }
                if (!response.ok) {
                    cancel();
                    setDriverInstallationInProgress(false);
                    setInstallationError(error);
                }
            });
        }
        return () => {
            if (db) {
                fetchResult?.cancel();
            }
        };
    }, [db, isDriverInstallationInProgress]);
    useEffect(() => {
        setTestConnectionLoading(false);
        setTestConnectionResult(null);
        setInstallationError(null);
        setHostname('');
    }, [db?.driver]);
    function handleDatabaseSelect(db) {
        return async () => {
            if (playgroundContext?.isDocker) {
                return selectDatabase(db);
            }
            {
                const response = await fetch(`/playground/driver?driver=${db.driver || ''}`);
                const { status, error } = await response.json();
                if (response.ok) {
                    if (status === STATUS.INSTALLED) {
                        return selectDatabase(db);
                    }
                    else if (status === STATUS.INSTALLING) {
                        setDriverInstallationInProgress(true);
                        selectDatabase(db);
                    }
                }
                else {
                    setInstallationError(error);
                }
            }
            {
                const response = await fetch('playground/driver', {
                    method: 'post',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        driver: db.driver,
                    }),
                });
                const { dependency, error } = await response.json();
                if (response.ok) {
                    setDependencyName(dependency);
                    setDriverInstallationInProgress(true);
                    selectDatabase(db);
                }
                else {
                    setInstallationError(error);
                }
            }
        };
    }
    if (installationError) {
        return (_jsx(Layout, { children: _jsx(FatalError, { error: installationError }) }));
    }
    if (isDriverInstallationInProgress && dependencyName) {
        return (_jsxs(Layout, { children: [_jsx(Title, { children: "Set Up a Database connection" }), _jsxs(Space, { align: "center", size: "middle", children: [_jsx(Spin, {}), _jsxs(Typography.Text, { children: ["Installing ", _jsx("b", { children: dependencyName })] })] })] }));
    }
    return (_jsxs(Layout, { children: [_jsx(Title, { children: "Set Up a Database connection" }), db ? (_jsx(_Fragment, { children: _jsxs(Space, { direction: "vertical", size: "large", style: { width: '100%' }, children: [_jsxs(Space, { size: "middle", children: [_jsx(SelectedDatabaseCard, { db: db }), _jsx(Button, { "data-testid": "wizard-change-db-btn", type: "link", onClick: () => selectDatabase(null), children: "Change" })] }), _jsxs(Typography, { children: [db.instructions ? (_jsx("div", { dangerouslySetInnerHTML: { __html: db.instructions } })) : (_jsxs(Typography.Paragraph, { children: ["Enter database credentials to connect to your database. ", _jsx("br", {}), "Cube will store your credentials into the ", _jsx("code", { children: ".env" }), ' ', "file for future use."] })), _jsx(Alert, { type: "info", message: _jsxs(_Fragment, { children: ["For advanced configuration, use the ", _jsx("b", { children: "cube.js" }), " or", ' ', _jsx("b", { children: ".env" }), " configuration files in your Cube project. Note these files are on the mount volume if you are running Docker.", _jsx("br", {}), _jsx(Typography.Link, { href: "https://cube.dev/docs/config/databases", target: "_blank", children: "Learn more about connecting to databases in the documentation." })] }) }), db.title === 'MongoDB' ? (_jsx(Alert, { message: "The MongoDB Connector for BI is required to connect to MongoDB.", type: "info" })) : null] }), _jsxs(Row, { gutter: [40, 12], children: [_jsx(Col, { span: 12, children: _jsxs(Space, { direction: "vertical", size: "large", style: { width: '100%' }, children: [_jsx(DatabaseForm, { db: db, deployment: {}, loading: isLoading, disabled: isTestConnectionLoading, hostname: hostname, onSubmit: async (variables) => {
                                                    try {
                                                        setTestConnectionResult(null);
                                                        setTestConnectionLoading(true);
                                                        await testConnection(variables);
                                                        setTestConnectionResult({
                                                            success: true,
                                                        });
                                                        setLoading(true);
                                                        await saveConnection(variables);
                                                        setLoading(false);
                                                        event('test_database_connection_success:frontend', {
                                                            database: db.title,
                                                        });
                                                        history.push('/schema');
                                                    }
                                                    catch (error) {
                                                        setTestConnectionResult({
                                                            success: false,
                                                            error,
                                                        });
                                                        event('test_database_connection_error:frontend', {
                                                            error: error.message || error.toString(),
                                                            database: db.title,
                                                        });
                                                    }
                                                    setTestConnectionLoading(false);
                                                } }), _jsx(ConnectionTest, { loading: isTestConnectionLoading, result: testConnectionResult })] }) }), ['MySQL', 'PostgreSQL', 'Druid', 'ClickHouse', 'Crate'].includes(db?.title || '') && playgroundContext?.isDocker ? (_jsx(Col, { span: 12, children: _jsx(LocalhostTipBox, { onHostnameCopy: setHostname }) })) : null] })] }) })) : (_jsxs(_Fragment, { children: [_jsx(Paragraph, { children: "Select a database type" }), _jsx(Row, { gutter: [12, 12], children: databases.map((db) => (_jsx(Col, { xl: 8, lg: 8, md: 12, sm: 24, xs: 24, children: _jsx(DatabaseCardWrapper, { onClick: handleDatabaseSelect(db), children: _jsx(DatabaseCard, { db: db }) }) }, db.title))) })] }))] }));
}
//# sourceMappingURL=ConnectionWizardPage.js.map