import { __awaiter } from "tslib";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
import React from "react";
import { Delete, Plus, Swap } from "@feedloop/icon";
import { Box, Text, Button, FormControl, Icon, Input, InputGroup, Select, VStack, HStack, Accordion, AccordionItem, AccordionButton, AccordionIcon, AccordionPanel, IconButton, FormLabel, Tooltip, Divider, Spacer, Grid, GridItem, } from "@chakra-ui/react";
import { Controller, useFieldArray, useForm, useWatch, } from "react-hook-form";
import { css } from "@emotion/react";
import { RuntimeContext } from "@qorebase/app-runtime/src/RuntimeContext";
import SwaggerParser from "@apidevtools/swagger-parser";
const resolveField = (field, [firstPath, ...paths]) => field.type === "object"
    ? (firstPath &&
        field.properties[firstPath] &&
        resolveField(field.properties[firstPath], paths)) ||
        field
    : field;
const fetchAndParseSchema = (url) => fetch(url)
    .then((response) => response.json())
    .then((json) => SwaggerParser.dereference(json));
const initialForm = {
    name: "",
    schemaUrl: "",
    selector: "",
    headers: [{ name: "", value: "" }],
};
const DataSource = (props) => {
    const { customSource, onSave } = props;
    const form = useForm({
        defaultValues: Object.assign(Object.assign({}, initialForm), { name: customSource === null || customSource === void 0 ? void 0 : customSource.name, schemaUrl: customSource === null || customSource === void 0 ? void 0 : customSource.schemaUrl, path: customSource === null || customSource === void 0 ? void 0 : customSource.path, method: customSource === null || customSource === void 0 ? void 0 : customSource.method, selector: customSource === null || customSource === void 0 ? void 0 : customSource.selector, headers: (customSource === null || customSource === void 0 ? void 0 : customSource.headers)
                ? Object.entries(customSource.headers).map(([name, value]) => ({
                    name,
                    value,
                }))
                : initialForm.headers }),
        mode: "onChange",
    });
    const runtimeActions = RuntimeContext.useActions();
    const [loading, setLoading] = React.useState(false);
    const [schema, setSchema] = React.useState(null);
    const schemaUrl = useWatch({
        name: "schemaUrl",
        control: form.control,
    });
    const path = useWatch({ name: "path", control: form.control });
    React.useEffect(() => {
        if (customSource) {
            fetchAndParseSchema(customSource.schemaUrl).then(setSchema);
        }
    }, [customSource]);
    const checkHandler = React.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        setLoading(true);
        setSchema(yield fetchAndParseSchema(schemaUrl));
        setLoading(false);
    }), [schemaUrl]);
    const handleAddCustomData = React.useCallback((formFields) => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
        if (!schema)
            return;
        const params = (((_b = (_a = schema.paths[formFields.path]) === null || _a === void 0 ? void 0 : _a[formFields.method.toLowerCase()]) === null || _b === void 0 ? void 0 : _b.parameters) || []).map((param) => ({
            slug: param.name,
            type: param.schema.type,
            required: param.required,
        }));
        const fields = (_h = (_g = (_f = (_e = (_d = (_c = schema.paths[formFields.path]) === null || _c === void 0 ? void 0 : _c[formFields.method.toLowerCase()]) === null || _d === void 0 ? void 0 : _d.responses) === null || _e === void 0 ? void 0 : _e["200"]) === null || _f === void 0 ? void 0 : _f.content) === null || _g === void 0 ? void 0 : _g["application/json"]) === null || _h === void 0 ? void 0 : _h.schema;
        const headers = Object.fromEntries(((_j = formFields.headers) === null || _j === void 0 ? void 0 : _j.map((header) => [header.name, header.value])) || []);
        runtimeActions.addCustomSources(Object.assign(Object.assign({ type: "openapi" }, formFields), { host: ((_l = (_k = schema.servers) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.url) || "", headers,
            params, columns: resolveField(fields, formFields.selector.split(".")) }));
        if (!customSource) {
            form.reset(initialForm);
        }
        onSave === null || onSave === void 0 ? void 0 : onSave();
    }, [runtimeActions, schema, customSource, onSave]);
    const fieldArray = useFieldArray({ control: form.control, name: "headers" });
    return (_jsx(Box, Object.assign({ width: "full", as: "form", onSubmit: form.handleSubmit(handleAddCustomData) }, { children: _jsx(Accordion, Object.assign({ allowToggle: true, defaultIndex: customSource ? [1] : [0] }, { children: _jsxs(AccordionItem, { children: [_jsx("h2", { children: _jsxs(AccordionButton, Object.assign({ css: css `
                &:hover button[aria-label="Go to domain"] {
                  background-color: #f5f5f5;
                }
                &:hover button[aria-label="Go to domain"] svg {
                  background-color: #f5f5f5;
                }
              ` }, { children: [_jsx(Box, Object.assign({ flex: "1", textAlign: "left" }, { children: customSource ? customSource.name : "New Data Source" })), _jsx(AccordionIcon, {})] })) }), _jsx(AccordionPanel, Object.assign({ pb: 4 }, { children: _jsxs(VStack, Object.assign({ spacing: 4 }, { children: [_jsxs(FormControl, { children: [_jsx(FormLabel, Object.assign({ fontSize: "md", mb: "11px" }, { children: "Source Name" })), _jsx(InputGroup, Object.assign({ width: "full", size: "sm" }, { children: _jsx(Input, { name: "name", placeholder: "Input source name", ref: form.register({ required: true }) }) }))] }), _jsxs(FormControl, { children: [_jsx(Box, Object.assign({ p: "0px", m: "0px" }, { children: _jsx(FormLabel, Object.assign({ fontSize: "md", mb: "11px" }, { children: "Schema URL" })) })), _jsxs(InputGroup, Object.assign({ width: "full", size: "sm" }, { children: [_jsx(Input, { name: "schemaUrl", placeholder: "Input schema URL", ref: form.register({ required: true }) }), _jsx(Tooltip, Object.assign({ label: "Check schema" }, { children: _jsx(IconButton, { onClick: checkHandler, "aria-label": "check-schema", size: "sm", isLoading: loading, icon: _jsx(Swap, {}) }) }))] }))] }), _jsx(Divider, {}), schema && Object.prototype.hasOwnProperty.call(schema, "paths") && (_jsxs(_Fragment, { children: [_jsxs(FormControl, { children: [_jsx(FormLabel, Object.assign({ fontSize: "md", mb: "11px" }, { children: "Path" })), _jsxs(Select, Object.assign({ width: "full", size: "sm", name: "path", ref: form.register({ required: true }) }, { children: [_jsx("option", { children: "Please choose your path" }), Object.keys(schema.paths).map((key) => (_jsx("option", Object.assign({ value: key }, { children: key }), key)))] }))] }), _jsxs(FormControl, { children: [_jsx(FormLabel, Object.assign({ fontSize: "md", mb: "11px" }, { children: "Method" })), _jsxs(Select, Object.assign({ width: "full", size: "sm", name: "method", ref: form.register({ required: true }) }, { children: [_jsx("option", { children: "Please choose your method" }), path &&
                                                            schema.paths[path] &&
                                                            Object.keys(schema.paths[path]).map((key) => (_jsx("option", Object.assign({ value: key.toUpperCase() }, { children: key.toUpperCase() }), key)))] }))] }), _jsxs(FormControl, { children: [_jsx(FormLabel, Object.assign({ fontSize: "md", mb: "11px" }, { children: _jsxs(HStack, { children: [_jsx(Text, { children: "Header" }), _jsx(Spacer, {}), _jsx(Icon, { cursor: "pointer", as: Plus }), _jsx(Text, Object.assign({ cursor: "pointer", fontSize: "md", onClick: () => {
                                                                    fieldArray.append({ name: "", value: "" });
                                                                } }, { children: "Add More Header" }))] }) })), fieldArray.fields.length > 0 && (_jsxs(Grid, Object.assign({ templateColumns: "repeat(5, 1fr)", gap: 4, mb: "10px" }, { children: [_jsx(GridItem, Object.assign({ colSpan: 2 }, { children: _jsx(Text, { children: "Name" }) })), _jsx(GridItem, Object.assign({ colSpan: 2 }, { children: _jsx(Text, { children: "Value" }) })), _jsx(GridItem, { colSpan: 1 })] }))), fieldArray.fields.map((field, index) => (_jsxs(Grid, Object.assign({ templateColumns: "repeat(5, 1fr)", gap: 4, mb: "10px" }, { children: [_jsx(GridItem, Object.assign({ colSpan: 2 }, { children: _jsx(InputGroup, { children: _jsx(Controller, { as: _jsx(Input, { placeholder: "Input name", size: "sm" }), name: `headers.${index}.name`, control: form.control }) }) })), _jsx(GridItem, Object.assign({ colSpan: 2 }, { children: _jsx(InputGroup, { children: _jsx(Controller, { as: _jsx(Input, { placeholder: "Input name", size: "sm" }), name: `headers.${index}.value`, control: form.control }) }) })), _jsx(GridItem, Object.assign({ colSpan: 1, pt: "5px" }, { children: _jsx(Delete, { width: "18px", height: "20px", onClick: () => fieldArray.remove(index) }) }))] }), field.id)))] }), _jsxs(FormControl, { children: [_jsx(FormLabel, Object.assign({ fontSize: "md", mb: "11px" }, { children: "Selector" })), _jsx(InputGroup, Object.assign({ width: "full", size: "sm" }, { children: _jsx(Input, { name: "selector", placeholder: "Input selector value", ref: form.register({ required: false }) }) }))] }), _jsxs(FormControl, { children: [_jsx(Button, Object.assign({ w: "48%", size: "sm", mr: "10px", display: customSource ? "none" : "initial" }, { children: "Cancel" })), _jsx(Button, Object.assign({ w: "48%", size: "sm", mr: "10px", bgColor: "#DE220B", color: "white", display: customSource ? "initial" : "none", onClick: () => {
                                                        runtimeActions.removeCustomSources(customSource.name);
                                                    } }, { children: "Delete" })), _jsx(Button, Object.assign({ w: "48%", size: "sm", type: "submit", bg: "#0065FF", color: "white" }, { children: "Save" }))] })] }))] })) }))] }) })) })));
};
export default function ExternalDataSource() {
    const currentCustomData = RuntimeContext.useSelectState((state) => state.customSources);
    const [createData, setCreateData] = React.useState(false);
    return (_jsx(Box, { children: _jsxs(VStack, Object.assign({ spacing: 2, width: "full" }, { children: [_jsx(Text, Object.assign({ w: "full", align: "left", fontSize: "md", fontWeight: "600", mb: "16px" }, { children: "External Data Option" })), _jsx(Box, Object.assign({ width: "full" }, { children: _jsxs(HStack, { children: [_jsx(Icon, { cursor: "pointer", as: Plus }), _jsx(Text, Object.assign({ cursor: "pointer", fontSize: "md", onClick: () => {
                                    setCreateData(true);
                                } }, { children: "Add Data Source" }))] }) })), _jsx(Text, Object.assign({ w: "full", align: "left", fontSize: "md", mb: "11px" }, { children: "External data list" })), Object.values(currentCustomData).map((value) => {
                    return _jsx(DataSource, { customSource: value }, value.name);
                }), createData && _jsx(DataSource, { onSave: () => setCreateData(false) })] })) }));
}
//# sourceMappingURL=ExternalDataSource.js.map