import {
    useState,
    useRef,
    type FC
} from "react";
import {
    TouchableOpacity,
    ScrollView,
    TextInput,
    View
} from "react-native";
import type {
    MarkdownEditorMode
} from "./type";
import type IMarkdownEditorProps from "./type";
import stylesheet, {
    useStyles
} from "./stylesheet";
import {
    NCoreUIKitLocalize,
    NCoreUIKitTheme
} from "../../core/hooks";
import type {
    TextMarkdownTypes,
    MarkdownKeys
} from "../markdownViewer/type";
import {
    ChevronsDown as ChevronsDownIcon,
    ChevronDown as ChevronDownIcon,
    AlignCenter as AlignCenterIcon,
    AlignRight as AlignRightIcon,
    AlignLeft as AlignLeftIcon,
    Italic as ItalicIcon,
    Quote as QuoteIcon,
    Image as ImageIcon,
    Bold as BoldIcon,
    Link as LinkIcon,
    Code as CodeIcon,
    List as ListIcon
} from "lucide-react-native";
import {
    DEFAULT_VARIANTS
} from "../markdownViewer/constant";
import {
    webStyle
} from "../../utils";
import MarkdownViewer from "../markdownViewer";
import Text from "../text";

const MarkdownEditor: FC<IMarkdownEditorProps> = ({
    spreadBehaviour = "stretch",
    isEditorResizable = true,
    isViewerResizable = true,
    toolbarContainerStyle,
    defaultMode = "live",
    initialValue = "",
    onChangeText,
    variants,
    style,
    ...props
}) => {
    const {
        radiuses,
        borders,
        colors,
        spaces
    } = NCoreUIKitTheme.useContext();

    const {
        localize
    } = NCoreUIKitLocalize.useContext();

    const [
        text,
        setText
    ] = useState<string>(initialValue);

    const [
        mode,
        setMode
    ] = useState<MarkdownEditorMode>(defaultMode);

    const [
        selection,
        setSelection
    ] = useState<{ end: number; start: number } | null>(null);

    const [
        isAutoScrollEnabled,
        setIsAutoScrollEnabled
    ] = useState<boolean>(true);

    const previewScrollRef = useRef<ScrollView>(null);

    const dynamicStyles = useStyles({
        spreadBehaviour,
        radiuses,
        borders,
        colors,
        spaces
    });

    const handleAction = (prefix: string, suffix: string, placeholder: string) => {
        let newText = "";

        if (selection && selection.start !== selection.end) {
            const before = text.substring(0, selection.start);
            const selected = text.substring(selection.start, selection.end);
            const after = text.substring(selection.end);

            const hasPrefix = prefix !== "" && selected.startsWith(prefix);
            const hasSuffix = suffix !== "" && selected.endsWith(suffix);

            const hasOuterPrefix = prefix !== "" && before.endsWith(prefix);
            const hasOuterSuffix = suffix !== "" && after.startsWith(suffix);

            if (
                (prefix === "" || hasPrefix) &&
                (suffix === "" || hasSuffix) &&
                (prefix !== "" || suffix !== "")
            ) {
                const stripped = selected.substring(prefix.length, selected.length - suffix.length);
                newText = before + stripped + after;
            } else if (
                (prefix === "" || hasOuterPrefix) &&
                (suffix === "" || hasOuterSuffix) &&
                (prefix !== "" || suffix !== "")
            ) {
                const newBefore = before.substring(0, before.length - prefix.length);
                const newAfter = after.substring(suffix.length);
                newText = newBefore + selected + newAfter;
            } else {
                newText = before + prefix + selected + suffix + after;
            }
        } else {
            const insertPos = selection ? selection.start : text.length;
            const before = text.substring(0, insertPos);
            const after = text.substring(insertPos);
            newText = before + prefix + placeholder + suffix + after;
        }

        setText(newText);
        onChangeText?.(newText);
    };

    const handleTypographySelect = (syntax: string) => {
        let prefix = syntax;
        let suffix = "";

        if (syntax === "<p>") {
            prefix = "<p>";
            suffix = "</p>";
        }

        if (selection && selection.start !== selection.end) {
            const before = text.substring(0, selection.start);
            const selected = text.substring(selection.start, selection.end);
            const after = text.substring(selection.end);

            const prependNewline = before.length > 0 && !before.endsWith("\n");
            const finalPrefix = (prependNewline ? "\n" : "") + prefix;

            const appendNewline = after.length > 0 && !after.startsWith("\n");
            const finalSuffix = suffix + (appendNewline ? "\n" : "");

            const newText = before + finalPrefix + selected + finalSuffix + after;

            setText(newText);
            onChangeText?.(newText);
        } else {
            const insertPos = selection ? selection.start : text.length;
            const before = text.substring(0, insertPos);
            const after = text.substring(insertPos);

            const prependNewline = before.length > 0 && !before.endsWith("\n");
            const finalPrefix = (prependNewline ? "\n" : "") + prefix;

            const newText = before + finalPrefix + suffix + after;

            setText(newText);
            onChangeText?.(newText);
        }
    };

    const renderToolbar = () => {
        const activeVariants = {
            ...DEFAULT_VARIANTS,
            ...variants
        };

        const textSyntaxKeys: TextMarkdownTypes[] = [
            "# ",
            "## ",
            "### ",
            "#### ",
            "##### ",
            "###### ",
            "<p>"
        ];
        const typographyKeysToRender = textSyntaxKeys.map(syntax => ({
            typographyKey: activeVariants[syntax as MarkdownKeys],
            syntax
        })).filter(item => item.typographyKey);

        return <View
            style={[
                stylesheet.toolbarContainer,
                dynamicStyles.toolbarContainer,
                toolbarContainerStyle
            ]}
        >
            <TouchableOpacity
                onPress={() => handleAction("**", "**", "bold")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <BoldIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("__", "__", "italic")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <ItalicIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <View
                style={[
                    stylesheet.toolbarSeparator,
                    dynamicStyles.toolbarSeparator
                ]}
            />
            <TouchableOpacity
                onPress={() => handleAction("<link href=\"https://nibgat.com\">\n", "\n</link>", "title")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <LinkIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("[", "](https://nibgat.com/assets/images/logo.png)", "alt")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <ImageIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("```\n", "\n```", "code")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <CodeIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("\n* ", "", "list item")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <ListIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("\n<<\n", "\n>>\n", "quote")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <QuoteIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <View
                style={[
                    stylesheet.toolbarSeparator,
                    dynamicStyles.toolbarSeparator
                ]}
            />
            <TouchableOpacity
                onPress={() => handleAction("<left>\n", "\n</left>", "content")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <AlignLeftIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("<center>\n", "\n</center>", "content")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <AlignCenterIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <TouchableOpacity
                onPress={() => handleAction("<right>\n", "\n</right>", "content")}
                style={[
                    stylesheet.toolbarAction,
                    dynamicStyles.toolbarAction
                ]}
            >
                <AlignRightIcon
                    color={colors.content.icon.mid}
                    size={18}
                />
            </TouchableOpacity>
            <View
                style={[
                    stylesheet.toolbarSeparator,
                    dynamicStyles.toolbarSeparator
                ]}
            />
            <ScrollView
                showsHorizontalScrollIndicator={false}
                style={stylesheet.typographyScroll}
                horizontal
            >
                {typographyKeysToRender.map((item) => {
                    return <TouchableOpacity
                        onPress={() => handleTypographySelect(item.syntax)}
                        style={[
                            stylesheet.typographyPill,
                            dynamicStyles.typographyPill
                        ]}
                        key={item.typographyKey}
                    >
                        <Text
                            color="mid"
                        >
                            {localize(`typography-${item.typographyKey}` as Parameters<typeof localize>[0])}
                        </Text>
                    </TouchableOpacity>;
                })}
            </ScrollView>
            <View
                style={stylesheet.switchContainer}
            >
                <TouchableOpacity
                    style={[
                        stylesheet.toolbarAction,
                        dynamicStyles.toolbarAction,
                        {
                            backgroundColor: isAutoScrollEnabled ? colors.content.container.primary : "transparent"
                        }
                    ]}
                    onPress={() => setIsAutoScrollEnabled(!isAutoScrollEnabled)}
                >
                    {
                        isAutoScrollEnabled ?
                            <ChevronsDownIcon
                                color={colors.content.text.constrastHigh}
                                size={18}
                            />
                        :
                            <ChevronDownIcon
                                color={colors.content.icon.mid}
                                size={18}
                            />
                    }
                </TouchableOpacity>
            </View>
        </View>;
    };

    return <View
        style={[
            stylesheet.container,
            dynamicStyles.container,
            style
        ]}
    >
        <View
            style={[
                stylesheet.tabsContainer,
                dynamicStyles.tabsContainer
            ]}
        >
            <TouchableOpacity
                style={[
                    stylesheet.tabButton,
                    mode === "live" ? dynamicStyles.tabButtonActive : dynamicStyles.tabButtonInactive
                ]}
                onPress={() => setMode("live")}
            >
                <Text
                    customColor={mode === "live" ? colors.content.text.emphasized : undefined}
                    color={mode === "live" ? undefined : "mid"}
                >
                    {localize("live")}
                </Text>
            </TouchableOpacity>
            <TouchableOpacity
                style={[
                    stylesheet.tabButton,
                    mode === "write" ? dynamicStyles.tabButtonActive : dynamicStyles.tabButtonInactive
                ]}
                onPress={() => setMode("write")}
            >
                <Text
                    customColor={mode === "write" ? colors.content.text.emphasized : undefined}
                    color={mode === "write" ? undefined : "mid"}
                >
                    {localize("write")}
                </Text>
            </TouchableOpacity>
            <TouchableOpacity
                style={[
                    stylesheet.tabButton,
                    mode === "preview" ? dynamicStyles.tabButtonActive : dynamicStyles.tabButtonInactive
                ]}
                onPress={() => setMode("preview")}
            >
                <Text
                    customColor={mode === "preview" ? colors.content.text.emphasized : undefined}
                    color={mode === "preview" ? undefined : "mid"}
                >
                    {localize("preview")}
                </Text>
            </TouchableOpacity>
        </View>
        {
            (mode === "live" || mode === "preview") &&
                <View
                    style={[
                        stylesheet.previewContainer,
                        dynamicStyles.previewContainer,
                        mode === "live" ? {
                            overflow: "hidden",
                            marginBottom: 10,
                            minHeight: 100,
                            height: 250,
                            ...(isViewerResizable ? webStyle({
                                resize: "vertical"
                            }) : {})
                        } : {}
                    ]}
                >
                    {
                        mode === "live" ?
                            <ScrollView
                                onContentSizeChange={() => {
                                    if (isAutoScrollEnabled) {
                                        previewScrollRef.current?.scrollToEnd({
                                            animated: true
                                        });
                                    }
                                }}
                                ref={previewScrollRef}
                            >
                                <MarkdownViewer
                                    variants={variants}
                                    content={text}
                                />
                            </ScrollView>
                        :
                            <MarkdownViewer
                                variants={variants}
                                content={text}
                            />
                    }
                </View>
        }
        {
            (mode === "live" || mode === "write") &&
                <View>
                    {renderToolbar()}
                    <TextInput
                        {...props}
                        placeholderTextColor={colors.content.text.mid}
                        onSelectionChange={(e) => {
                            setSelection(e.nativeEvent.selection);
                            props.onSelectionChange?.(e);
                        }}
                        style={[
                            stylesheet.editorInput,
                            dynamicStyles.editorInput,
                            isEditorResizable ? webStyle({
                                resize: "vertical"
                            }) : {},
                            style
                        ]}
                        onChangeText={(val) => {
                            setText(val);
                            onChangeText?.(val);
                        }}
                        multiline={true}
                        value={text}
                    />
                </View>
        }
    </View>;
};
export default MarkdownEditor;
