import {
    type ReactNode
} from "react";
import {
    Platform
} from "react-native";
import {
    initializeInstances
} from "./hooks";
import type {
    NCoreUIKitConfig
} from "../types";
import {
    SafeAreaProvider
} from "react-native-safe-area-context";
import {
    WebScrollbar
} from "../components";
import packageJSON from "../../package.json";
import CoreContext from "../context";

export const getNCoreUIKitVersion = () => packageJSON.version;

export class NCoreUIKitBase<T extends NCoreUIKitConfig> {
    NCoreUIKitContext: CoreContext<T>;

    constructor(initialState: T) {
        this.NCoreUIKitContext = new CoreContext(initialState);
    }

    Provider = ({
        children
    }: {
        children: ReactNode;
    }) => {
        const NCoreUIKitContext = this.NCoreUIKitContext;

        return <SafeAreaProvider>
            <NCoreUIKitContext.Provider>
                <WebScrollbar/>
                {children}
            </NCoreUIKitContext.Provider>
        </SafeAreaProvider>;
    };
};

let NCoreUIKit!: NCoreUIKitBase<NCoreUIKitConfig>;

export const setupNCoreUIKit = (initialState: NCoreUIKitConfig, isCustom: boolean = false) => {
    if(isCustom) {
        return new NCoreUIKitBase(initialState);
    } else {
        NCoreUIKit = new NCoreUIKitBase(initialState);

        initializeInstances(NCoreUIKit);

        if (Platform.OS === "web") {
            const globalRef = globalThis as unknown as { document?: unknown };

            if (globalRef && typeof globalRef.document === "object" && globalRef.document !== null) {
                const doc = globalRef.document as {
                    createElement?: (tagName: string) => unknown;
                    getElementById?: (id: string) => unknown;
                    head?: unknown;
                };

                const styleId = "cl-rnw-touchable-fix";

                if (typeof doc.getElementById === "function" && !doc.getElementById(styleId)) {
                    if (typeof doc.createElement === "function" && doc.head && typeof doc.head === "object") {
                        const style = doc.createElement("style") as {
                            innerHTML?: string;
                            type?: string;
                            id?: string;
                        };

                        if (style) {
                            style.id = styleId;
                            style.type = "text/css";
                            style.innerHTML = `
                                html, body, #root {
                                    touch-action: none;
                                    overflow: hidden;
                                }

                                [role="button"],
                                [data-focusable="true"],
                                div[tabindex="0"] {
                                    cursor: pointer !important;
                                    transition: opacity 0.15s ease-in-out, transform 0.1s ease-in-out !important;
                                }

                                [role="button"]:not([data-disable-pressable-hover-effect="true"]):hover,
                                [data-focusable="true"]:not([data-disable-pressable-hover-effect="true"]):hover,
                                div[tabindex="0"]:not([data-disable-pressable-hover-effect="true"]):hover {
                                    opacity: 0.8 !important;
                                }

                                [role="button"]:not([data-disable-pressable-down-effect="true"]):active,
                                [data-focusable="true"]:not([data-disable-pressable-down-effect="true"]):active,
                                div[tabindex="0"]:not([data-disable-pressable-down-effect="true"]):active {
                                    opacity: 0.5 !important;
                                    transform: translateY(2px) !important;
                                }

                                input,
                                textarea,
                                select,
                                [role="textinput"],
                                div[tabindex]:focus {
                                    outline: none !important;
                                    box-shadow: none !important;
                                }
                            `;

                            const head = doc.head as { appendChild?: (node: unknown) => void };

                            if (typeof head.appendChild === "function") {
                                head.appendChild(style);
                            }
                        }
                    }
                }
            }
        }

        return NCoreUIKit;
    }
};
