import { __awaiter } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
import { Plus, GoTo, Edit, RotateRight, Copy, Delete, CheckCircle, Close, } from "@feedloop/icon";
import { Box, Text, Button, Icon, Input, InputGroup, InputRightAddon, VStack, HStack, IconButton, GridItem, SimpleGrid, useDisclosure, Collapse, Tag, CircularProgress, useToast, Modal, ModalOverlay, ModalContent, ModalHeader, ModalFooter, ModalBody, ModalCloseButton, Skeleton, } from "@chakra-ui/react";
import { useRouter } from "next/router";
import React from "react";
import getConfig from "next/config";
import subdomain from "../../utils/subdomain";
import qoreStorageClient from "../../hooks/qoreStorageClient";
import { css } from "@emotion/react";
import useUpdateWhitelist from "../../hooks/useUpdateWhitelist";
import { ChevronDownIcon } from "@chakra-ui/icons";
import useSWR from "swr";
import { parseDomain, ParseResultType } from "parse-domain";
const { publicRuntimeConfig } = getConfig();
const DomainStatus = (props) => {
    return (_jsxs(HStack, Object.assign({ alignItems: "center", mt: 3 }, { children: [_jsxs(Tag, Object.assign({ bg: props.validStatus === "ready" ? "#EBF5E9" : "#FCEAEB", p: "2px 8px", color: props.validStatus === "ready" ? "#329922" : "#E03138", fontSize: "12px", borderRadius: "4px", gap: "5px" }, { children: [props.isValidating && props.validStatus !== "ready" && (_jsx(CircularProgress, { size: "10px", isIndeterminate: true, color: "#E03138", mr: "5px" })), props.validStatus === "ready" && _jsx(CheckCircle, {}), props.validStatus === "ready"
                        ? "Valid Configuration"
                        : "Invalid Configuration"] })), _jsxs(Tag, Object.assign({ display: props.validStatus === "ready" ? "inline-flex" : "none", color: props.certStatus === "ready"
                    ? "#329922"
                    : props.isValidating
                        ? "#EE7105"
                        : "#E03138", gap: "5px", p: "2px 8px", bg: props.certStatus === "ready"
                    ? "#EBF5E9"
                    : props.isValidating
                        ? "#FDF1E6"
                        : "#FCEAEB", fontSize: "12px", borderRadius: "4px" }, { children: [props.certStatus === "ready" ? (_jsx(CheckCircle, {})) : props.isValidating ? (_jsx(CircularProgress, { size: "10px", isIndeterminate: true, color: "#EE7105", mr: "5px" })) : null, props.certStatus === "ready"
                        ? "Certificate Issued"
                        : props.isValidating
                            ? "Issueing Certificate"
                            : "Invalid Certificate"] }))] })));
};
const DomainList = (props) => {
    var _a, _b;
    const hostedRegex = new RegExp(publicRuntimeConfig.appsDomain, "g");
    const toast = useToast();
    const collapseDisclosure = useDisclosure({ defaultIsOpen: false });
    const modalDisclosure = useDisclosure({ defaultIsOpen: false });
    const [displayEdit, setDisplayEdit] = React.useState(false);
    const [newAddressValue, setNewAddressValue] = React.useState(props.address);
    const [isInputed, setIsInputed] = React.useState(false);
    const router = useRouter();
    const token = qoreStorageClient.useClient().project.config.getToken();
    const { data, isValidating, mutate } = useSWR(`/api/console/api/infra/custom-domain/${Number(router.query.projectID)}?address=${props.address}`, (apiURL) => __awaiter(void 0, void 0, void 0, function* () {
        return yield fetch(apiURL, {
            method: "GET",
            headers: {
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
                Authorization: `Bearer ${token}`,
            },
        }).then((res) => res.json());
    }), {
        isPaused() {
            if (props.type === "Hosted") {
                return true;
            }
            else {
                return false;
            }
        },
    });
    const parseResult = React.useMemo(() => {
        return parseDomain(newAddressValue);
    }, [newAddressValue]);
    const checkDomain = React.useMemo(() => {
        if (parseResult.type === ParseResultType.Listed) {
            const { subDomains, domain, topLevelDomains } = parseResult;
            if (subDomains.length <= 1 && domain && topLevelDomains) {
                return {
                    subDomains,
                    domain,
                    topLevelDomains,
                };
            }
        }
    }, [parseResult]);
    const newDomainValidation = React.useMemo(() => {
        if (props.type === "Hosted") {
            if (hostedRegex.test(newAddressValue)) {
                setNewAddressValue(newAddressValue.slice(0, newAddressValue.indexOf(publicRuntimeConfig.appsDomain)));
            }
            return true;
        }
        else {
            if (checkDomain) {
                return true;
            }
            else {
                if (newAddressValue === "" && !isInputed) {
                    return true;
                }
                return false;
            }
        }
    }, [newAddressValue, props.type]);
    const configText = [
        "Type",
        "Name",
        "Value",
        "CNAME",
        (checkDomain === null || checkDomain === void 0 ? void 0 : checkDomain.subDomains.length) === 0 ? "@" : checkDomain === null || checkDomain === void 0 ? void 0 : checkDomain.subDomains[0],
        `${publicRuntimeConfig.cnameValue}`,
    ];
    const toastDeleted = (status) => status === "success"
        ? toast({
            position: "bottom",
            duration: 3000,
            render: () => (_jsxs(Box, Object.assign({ p: 3, bg: "#329922", display: "flex", flexDirection: "row", alignItems: "center", w: "252px", justifyContent: "space-between", m: "auto", borderRadius: "4px" }, { children: [_jsx(Icon, { boxSize: "14px", as: CheckCircle, color: "white" }), _jsx(Text, Object.assign({ color: "white" }, { children: "Successfully deleted domain" })), _jsx(Icon, { boxSize: "14px", as: Close, color: "white", onClick: () => toast.closeAll(), cursor: "pointer" })] }))),
        })
        : toast({
            duration: 3000,
            status: "error",
            title: "Error",
        });
    return (_jsxs(Box, Object.assign({ padding: "12px 16px", border: "1px solid #E7E7E7", rounded: "md", mb: 4 }, { children: [_jsxs(VStack, Object.assign({ alignItems: "stretch", display: displayEdit ? "none" : "flex" }, { children: [_jsxs(HStack, Object.assign({ justifyContent: "space-between" }, { children: [_jsx(Text, { children: props.type === "Hosted"
                                    ? props.address + publicRuntimeConfig.appsDomain
                                    : props.address }), _jsxs(HStack, { children: [_jsx(Icon, { boxSize: "12px", as: RotateRight, cursor: "pointer", color: "#A2A2A2", _hover: { color: "#0065FF" }, display: props.type === "Hosted" ? "none" : "inline-block", onClick: () => __awaiter(void 0, void 0, void 0, function* () {
                                            yield mutate();
                                        }) }), _jsx(Icon, { boxSize: "12px", as: Edit, cursor: "pointer", color: displayEdit ? " #0065FF" : "#A2A2A2", onClick: () => {
                                            setDisplayEdit(true);
                                            collapseDisclosure.onClose();
                                        }, _hover: { color: "#0065FF" } }), _jsx(Icon, { boxSize: "12px", as: GoTo, cursor: "pointer", color: "#A2A2A2", onClick: () => window.open(`https://${props.type === "Hosted"
                                            ? props.address + publicRuntimeConfig.appsDomain
                                            : props.address}`, "_blank"), _hover: { color: "#0065FF" } }), _jsx(Icon, { boxSize: "12px", as: ChevronDownIcon, cursor: "pointer", color: "#A2A2A2", transition: "all 300ms ease-out", transform: `rotate(${collapseDisclosure.isOpen ? -180 : 0}deg)`, onClick: collapseDisclosure.onToggle, _hover: { color: "#0065FF" }, display: props.type === "Hosted" ? "none" : "inline-block" })] })] })), props.type === "Custom" && (_jsx(DomainStatus, { validStatus: data && data.valid ? (_a = data.valid) === null || _a === void 0 ? void 0 : _a.status : "not ready", certStatus: data && data.cert && !isValidating
                            ? (_b = data.cert) === null || _b === void 0 ? void 0 : _b.status
                            : "not ready", isValidating: isValidating }))] })), _jsxs(Collapse, Object.assign({ style: { overflow: "revert" }, in: collapseDisclosure.isOpen, animateOpacity: true }, { children: [_jsx(Text, Object.assign({ mt: "18px", mb: 3 }, { children: "Set the following record on your DNS provider to continue:" })), _jsx(Box, Object.assign({ p: 4, bg: "#F5F5F5", borderRadius: "4px" }, { children: _jsxs(HStack, Object.assign({ justifyContent: "space-between", alignItems: "end" }, { children: [_jsx(SimpleGrid, Object.assign({ columns: 3, spacingY: 2, spacingX: 4, templateRows: "repeat(2, 1fr)", templateColumns: "repeat(8, 1fr)" }, { children: configText.map((txt, idx) => (_jsx(GridItem, Object.assign({ colSpan: idx === 2 || idx === 5 ? 4 : 2 }, { children: _jsx(Text, Object.assign({ fontSize: "12px", color: idx > 2 ? "#747474" : "#001E4D" }, { children: txt }), idx) }), idx))) })), _jsx(Icon, { boxSize: "12px", as: Copy, cursor: "pointer", color: "#A2A2A2", onClick: () => {
                                        navigator.clipboard.writeText(`${publicRuntimeConfig.cnameValue}`);
                                        toast({
                                            duration: 3000,
                                            title: "Copied to the clipboard!.",
                                            status: "info",
                                            isClosable: true,
                                        });
                                    } })] })) }))] })), _jsxs(Box, Object.assign({ display: displayEdit ? "block" : "none" }, { children: [_jsxs(HStack, Object.assign({ justifyContent: "space-between", alignItems: "flex-start" }, { children: [_jsx(Text, Object.assign({ fontSize: "12px", height: "32px", pt: 2 }, { children: "Domain Value" })), _jsxs(VStack, Object.assign({ alignItems: "left", w: "80%" }, { children: [_jsxs(InputGroup, { children: [_jsx(Input, { value: newAddressValue, fontSize: "12px", height: "32px", m: 0, bg: "#E7E7E7", borderColor: !newDomainValidation ? "#E96F74" : "#E7E7E7", focusBorderColor: !newDomainValidation ? "#E96F74" : "#E7E7E7", onChange: (e) => {
                                                    setNewAddressValue(e.target.value);
                                                    setIsInputed(true);
                                                } }), props.type === "Hosted" && (_jsx(InputRightAddon, Object.assign({ p: "8px 12px", fontSize: "12px", height: "32px", m: 0, bg: "#F5F5F5" }, { children: publicRuntimeConfig.appsDomain })))] }), !newDomainValidation && (_jsx(Text, Object.assign({ fontSize: "12px", color: "#E03138", textAlign: "left" }, { children: "Invalid domain name" })))] }))] })), _jsxs(HStack, Object.assign({ justifyContent: "space-between", mt: 4 }, { children: [_jsxs(HStack, { children: [_jsx(Button, Object.assign({ isDisabled: newAddressValue === props.address ||
                                            props.updateStatus === "loading" ||
                                            !newDomainValidation ||
                                            newAddressValue === ""
                                            ? true
                                            : false, borderRadius: "4px", size: "sm", color: "white", bg: "#0065FF", _hover: { bg: "#0065FF" }, onClick: () => {
                                            Promise.resolve(props.onUpdate(props.id, props.type === "Hosted"
                                                ? newDomainValidation
                                                    ? newAddressValue
                                                    : newAddressValue.slice(0, newAddressValue.indexOf(publicRuntimeConfig.appsDomain))
                                                : newAddressValue, props.address, props.type)).then(() => setDisplayEdit(false));
                                        } }, { children: "Save" })), _jsx(Button, Object.assign({ borderRadius: "4px", size: "sm", bg: "white", border: "1px solid #E7E7E7", _hover: { bg: "white" }, onClick: () => {
                                            setDisplayEdit(false);
                                            setNewAddressValue(props.address);
                                        } }, { children: "Cancel" }))] }), _jsx(IconButton, { "aria-label": "Delete", bg: "white", _hover: { bg: "white" }, css: css `
              & :hover {
                background-color: white;
              }
            `, border: "1px solid #E7E7E7", size: "sm", icon: _jsx(Delete, {}), onClick: () => modalDisclosure.onOpen(), _active: { bg: "white" } })] }))] })), _jsxs(Modal, Object.assign({ isOpen: modalDisclosure.isOpen, onClose: modalDisclosure.onClose }, { children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { children: [_jsxs(ModalHeader, Object.assign({ fontSize: "md", display: "flex", alignItems: "center", gap: "13px" }, { children: [_jsx(Delete, { width: "18px", height: "20px", color: "#E03138" }), "Remove Domain From Project"] })), _jsx(ModalCloseButton, {}), _jsxs(ModalBody, Object.assign({ pl: "55px" }, { children: [_jsx(Text, Object.assign({ mb: 4 }, { children: `Would you like to remove the domain ${props.type === "Hosted"
                                            ? props.address + publicRuntimeConfig.appsDomain
                                            : props.address} from your
              project internal?` })), _jsx(Text, { children: "After continuing your project will no longer be accessible through this domain" })] })), _jsxs(ModalFooter, { children: [_jsx(Button, Object.assign({ variant: "outline", size: "sm", mr: 3, onClick: modalDisclosure.onClose }, { children: "Close" })), _jsx(Button, Object.assign({ disabled: props.deleteStatus === "loading", isLoading: props.deleteStatus === "loading", bg: "#E03138", color: "white", size: "sm", onClick: () => {
                                            Promise.resolve(props.type === "Custom"
                                                ? props.onDelete(props.id, props.address)
                                                : props.onDelete(props.id)).then(() => {
                                                modalDisclosure.onClose();
                                                toastDeleted("success");
                                            }, () => {
                                                modalDisclosure.onClose();
                                                toastDeleted("error");
                                            });
                                        } }, { children: "Delete" }))] })] })] }))] })));
};
export default function DomainSetting() {
    const hostedRegex = new RegExp(publicRuntimeConfig.appsDomain, "g");
    const router = useRouter();
    const token = qoreStorageClient.useClient().project.config.getToken();
    const [addressValue, setAddressValue] = React.useState("");
    const [isSubmitting, setIsSubmitting] = React.useState(false);
    const [isInputed, setIsInputed] = React.useState(false);
    const whitelistNewDomain = useUpdateWhitelist(router.query.projectID, router.query.appID);
    const toast = useToast();
    const errorToast = React.useCallback((title) => {
        toast({
            duration: 3000,
            title: title,
            status: "error",
        });
    }, [toast]);
    const parseResult = React.useMemo(() => {
        return parseDomain(addressValue);
    }, [addressValue]);
    const checkDomain = React.useMemo(() => {
        if (parseResult.type === ParseResultType.Listed) {
            const { subDomains, domain, topLevelDomains } = parseResult;
            if (subDomains.length <= 1 && domain && topLevelDomains) {
                return true;
            }
        }
    }, [parseResult]);
    const domainNameValidation = React.useMemo(() => {
        if (checkDomain) {
            if (hostedRegex.test(addressValue)) {
                return { isHosted: true, isValid: true };
            }
            else {
                return { isHosted: false, isValid: true };
            }
        }
        else {
            if (addressValue === "" && !isInputed) {
                return { isHosted: false, isValid: true };
            }
            return { isHosted: false, isValid: false };
        }
    }, [addressValue, isInputed]);
    const domains = qoreStorageClient.table("domains").useListRow({
        condition: {
            $and: [
                {
                    appdomain: {
                        $eq: router.query.appID,
                    },
                },
            ],
        },
    });
    const { insertRow: insertDomain } = qoreStorageClient
        .table("domains")
        .useInsertRow();
    const handleCreateRow = React.useCallback(() => __awaiter(this, void 0, void 0, function* () {
        yield insertDomain({
            address: subdomain(),
            type: "Hosted",
            application: [router.query.appID],
        });
        yield domains.revalidate();
    }), [insertDomain, router.query.appID]);
    const { deleteRow: deleteDomain, status: deleteStatus } = qoreStorageClient
        .table("domains")
        .useDeleteRow();
    const { updateRow: updateDomain, status: updateStatus } = qoreStorageClient
        .table("domains")
        .useUpdateRow();
    const handleUpdateCustomDomain = React.useCallback((id, newAddress, currentAddress, type) => __awaiter(this, void 0, void 0, function* () {
        try {
            yield whitelistNewDomain(newAddress, type === "Hosted" ? "Hosted" : "Custom");
            yield updateDomain(id, { address: newAddress });
            if (type === "Custom") {
                const updateDomain = yield fetch(`/api/console/api/infra/custom-domain/${Number(router.query.projectID)}`, {
                    method: "PUT",
                    headers: {
                        "Access-Control-Allow-Origin": "*",
                        "Content-type": "application/json",
                        Authorization: `Bearer ${token}`,
                    },
                    body: JSON.stringify({
                        currentAddress: currentAddress,
                        newAddress: newAddress,
                    }),
                });
                if (updateDomain.status >= 400 && updateDomain.status <= 500) {
                    throw new Error();
                }
            }
            yield domains.revalidate();
        }
        catch (_a) {
            errorToast("Failed updating data");
        }
    }), [
        updateDomain,
        domains.revalidate,
        whitelistNewDomain,
        router.query.projectID,
        token,
    ]);
    const handleDeleteCustomDomain = React.useCallback((id, address) => __awaiter(this, void 0, void 0, function* () {
        try {
            yield deleteDomain(id);
            if (address !== undefined) {
                const deleteDomain = yield fetch(`/api/console/api/infra/custom-domain/${Number(router.query.projectID)}`, {
                    method: "DELETE",
                    headers: {
                        "Access-Control-Allow-Origin": "*",
                        "Content-type": "application/json",
                        Authorization: `Bearer ${token}`,
                    },
                    body: JSON.stringify({
                        address: address,
                    }),
                });
                if (deleteDomain.status >= 400 && deleteDomain.status <= 500) {
                    throw new Error();
                }
            }
            yield domains.revalidate();
        }
        catch (_b) {
            throw new Error();
        }
    }), [deleteDomain, domains, router.query.projectID]);
    const handleAddCustomDomain = React.useCallback((e) => __awaiter(this, void 0, void 0, function* () {
        e.preventDefault();
        setIsInputed(true);
        try {
            if (domainNameValidation["isValid"] && addressValue !== "") {
                setIsSubmitting(true);
                yield whitelistNewDomain(domainNameValidation["isHosted"]
                    ? addressValue.slice(0, addressValue.indexOf(publicRuntimeConfig.appsDomain))
                    : addressValue, domainNameValidation["isHosted"] ? "Hosted" : "Custom");
                yield insertDomain({
                    address: domainNameValidation["isHosted"]
                        ? addressValue.slice(0, addressValue.indexOf(publicRuntimeConfig.appsDomain))
                        : addressValue,
                    type: domainNameValidation["isHosted"] ? "Hosted" : "Custom",
                    appdomain: [router.query.appID],
                });
                if (!domainNameValidation["isHosted"] &&
                    domainNameValidation["isValid"]) {
                    const addDomain = yield fetch("/api/console/api/infra/custom-domain/", {
                        method: "POST",
                        headers: {
                            "Access-Control-Allow-Origin": "*",
                            "Content-type": "application/json",
                            Authorization: `Bearer ${token}`,
                        },
                        body: JSON.stringify({
                            projectId: Number(router.query.projectID),
                            address: addressValue,
                        }),
                    });
                    if (addDomain.status >= 400 && addDomain.status <= 500) {
                        setIsSubmitting(false);
                        throw new Error();
                    }
                }
                yield domains.revalidate();
                setIsSubmitting(false);
                setAddressValue("");
                setIsInputed(false);
            }
        }
        catch (err) {
            setIsSubmitting(false);
            errorToast("Failed to submit");
        }
    }), [
        insertDomain,
        deleteDomain,
        whitelistNewDomain,
        router.query.appID,
        router.query.projectID,
        addressValue,
        domains.revalidate,
        domainNameValidation,
    ]);
    const customDomains = domains.data.filter((domain, idx) => idx !== 0);
    const address = domains.data.length !== 0
        ? domains.data[0].address +
            (domains.data[0].type === "Hosted"
                ? publicRuntimeConfig.appsDomain
                : "")
        : "";
    return domains.data.length === 0 ? (_jsxs(VStack, { children: [_jsx(Skeleton, { minH: "50px", w: "full" }), _jsx(Skeleton, { minH: "100px", w: "full" }), _jsx(Skeleton, { minH: "200px", w: "full" })] })) : (_jsxs(Box, { children: [_jsx(Text
            // w="full"
            , Object.assign({ 
                // w="full"
                align: "left", fontSize: "md", fontWeight: "600", mb: "16px" }, { children: "Domain" })), _jsx(Text, Object.assign({ fontSize: "14px", mb: 4 }, { children: "Create a domain so that this application can be accessed by others." })), _jsxs(SimpleGrid, Object.assign({ row: 2, mb: 4 }, { children: [_jsxs(HStack, { children: [_jsx(Input, { maxH: "32px", placeholder: "mydomain.com", borderColor: !domainNameValidation["isValid"] ? "#E96F74" : "#E7E7E7", focusBorderColor: !domainNameValidation["isValid"] ? "#E96F74" : "#E7E7E7", fontSize: "12px", _placeholder: { color: "#A2A2A2" }, value: addressValue, onChange: (e) => {
                                    setAddressValue(e.target.value);
                                    setIsInputed(true);
                                } }), _jsx(Button, Object.assign({ maxH: "32px", maxW: "95px", fontSize: "sm", width: "full", rounded: "md", bg: "#0065FF", color: "white", _hover: { bg: "#0065FF" }, isDisabled: isSubmitting ? true : false, onClick: handleAddCustomDomain }, { children: "Add Domain" }))] }), !domainNameValidation["isValid"] && (_jsx(Text, Object.assign({ mt: 2, fontSize: "12px", color: "#E03138" }, { children: "Invalid domain name" }))), _jsxs(Box, Object.assign({ mt: 4, py: 3, px: 4, border: "1px solid #E7E7E7", rounded: "md", display: "flex", alignItems: "center" }, { children: [_jsx(Text, Object.assign({ fontSize: "12px", mr: "10px" }, { children: address })), _jsx(IconButton, { "aria-label": "Go to domain", bg: "white", _hover: { bg: "white" }, css: css `
              & :hover {
                background-color: white;
              }
            `, color: "#A2A2A2", size: "12px", icon: _jsx(GoTo, { onClick: () => window.open(`https://${address}`, "_blank") }) })] }))] })), domains.data.length === 0 && (_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: handleCreateRow }, { children: "Add Domain" }))] }) }))), customDomains.map((domain, idx) => (_jsx(DomainList, { address: domain.address, type: domain.type, id: domain.id, onDelete: handleDeleteCustomDomain, onUpdate: handleUpdateCustomDomain, deleteStatus: deleteStatus, updateStatus: updateStatus }, idx)))] }));
}
//# sourceMappingURL=DomainSetting.js.map