import {
    type ForwardRefRenderFunction,
    type CSSProperties
} from "react";
import type {
    ImageStyle,
    TextStyle,
    ViewStyle
} from "react-native";
import {
    type INCoreUIKitIconCallbackProps
} from "./icon";
import {
    type LocalizeType,
    type LocaleType
} from "./locale";
import {
    type ModalDataType,
    type ModalType
} from "./modal";
import {
    type GapPropagationType,
    type SharpnessType,
    type ThemeConfigs,
    type PaletteType,
    type ThemesType,
    type ThemeType
} from "./theme";
import defaultLocaleJSON from "../variants/locales/default.json";
import defaultThemeJSON from "../variants/themes/default.json";

export type {
    PortalizedComponentProps
} from "./portalize";

export type {
    INCoreUIKitIconCallbackProps,
    INCoreUIKitIconProps,
    NCoreUIKitIcon
} from "./icon";

export type {
    ThemeContextStateType,
    ThemeContextType,
    ThemeConfigs
} from "./theme";

export type {
    LocalizeContextStateType,
    LocalizeContextType
} from "./locale";

export type {
    GapPropagationType,
    NCoreUIKitConfig,
    SharpnessType,
    ModalDataType,
    LocalizeType,
    PaletteType,
    ThemesType,
    LocaleType,
    ModalType,
    ThemeType
};

export type ActivityStatusType = "online" | "offline" | "busy" | "away" | "idle";

export type PureRNStyles = Omit<ViewStyle & TextStyle & ImageStyle, "position" | "cursor" | "filter">;

export type PureWebStyles = Omit<CSSProperties, "position" | "cursor" | "filter">;

export type AllStyles = PureRNStyles & PureWebStyles & {
    position?: CSSProperties["position"];
    cursor?: CSSProperties["cursor"];
    filter?: string;
};

export type RecursiveRecord = {
  [key: string]: string | RecursiveRecord;
};

export interface RefForwardingComponent<T, P = object> extends ForwardRefRenderFunction<T, P> {};

export interface SafePointerEvent {
    clientY: number;
}

export interface SafeWebWindow {
    removeEventListener: (type: "pointermove" | "pointerup", listener: (evt: SafePointerEvent) => void) => void;
    addEventListener: (type: "pointermove" | "pointerup", listener: (evt: SafePointerEvent) => void) => void;
}

export const safeGlobal = globalThis as unknown as SafeWebWindow;

export type Mutable<T> = {
    -readonly [P in keyof T]: T[P];
};

type NCoreUIKitConfig = ThemesType & LocalizeType & ModalType;

declare global {
    namespace NCoreUIKit {
        interface GapPropagationKey extends Record<GapPropagationType, unknown> {}
        interface SharpnessKey extends Record<SharpnessType, unknown> {}
        interface PaletteKey extends Record<PaletteType, unknown> {}
        interface LocaleKey extends Record<LocaleType, unknown> {}
        interface ThemeKey extends Record<ThemeType, unknown> {}

        type IconCallbackProps = INCoreUIKitIconCallbackProps;

        interface ActivePalette {
            inlineSpaces: InlineSpaces;
            shapeConfigs: ShapeConfigs;
            typography: Typography;
            configs: ThemeConfigs;
            colors: ThemeTokens;
            radiuses: Radiuses;
            borders: Borders;
            spaces: Spaces;
        }

        interface Palette {
            isNeedAndroidTypographyFixer: boolean;
            typography: TypographyWithVariants;
            palettes: ThemePalettes;
            shapes: Shapes;
        }

        type SpacesWithVariants = Record<GapPropagationType, Spaces>;

        type RadiusesWithVariants = Record<SharpnessType, Radiuses>;

        type Shapes = {
            radiuses: RadiusesWithVariants;
            inlineSpaces: InlineSpaces;
            shapeConfigs: ShapeConfigs;
            spaces: SpacesWithVariants;
            borders: Borders;
        };

        type DefaultSpaces = Record<keyof typeof defaultThemeJSON.shapes.spaces.compact, number>;

        interface Spaces extends DefaultSpaces {}

        type DefaultBorders = Record<keyof typeof defaultThemeJSON.shapes.borders, number>;

        interface Borders extends DefaultBorders {
        }

        type DefaultInlineSpaces = Record<keyof typeof defaultThemeJSON.shapes.inlineSpaces, number>;

        interface InlineSpaces extends DefaultInlineSpaces {
        }

        type DefaultShapeConfigs = Record<keyof typeof defaultThemeJSON.shapes.shapeConfigs, number>;

        interface ShapeConfigs extends DefaultShapeConfigs {
        }

        type DefaultRadiuses = Record<keyof typeof defaultThemeJSON.shapes.radiuses.rounded, number>;

        interface Radiuses extends DefaultRadiuses {}

        type TypographyWithVariants = Record<GapPropagationType, Typography>;

        type DefaultTypography = Record<keyof typeof defaultThemeJSON.typography.compact, TypographyToken>;

        interface Typography extends DefaultTypography {}

        interface TypographyToken {
            letterSpacing: number;
            fontWeight: string;
            fontFamily: string;
            lineHeight: number;
            fontSize: number;
        }

        type ThemePalettes = Array<ThemePalette>;

        interface ThemePalette {
            themes: Theme;
            name: string;
        }

        type Theme = Record<keyof ThemeKey, ThemeTokens>;

        type ColorsMerged = DefaultSystemColors & DefaultContentColors;

        type ThemeTokens = {
            project: ProjectColorPalette;
            content: ContentColorPalette;
            system: SystemColorPalette;
            code: CodeColorPalette;
        };

        type DefaultPalette = typeof defaultThemeJSON.palettes[0];

        type DefaultLowColors = typeof defaultThemeJSON.palettes[0]["themes"]["dark"]["system"]["low"];

        interface LowColors extends DefaultLowColors {
        }

        type ProjectData = DefaultPalette["themes"]["dark"]["project"];
        type DefaultProjectColors = ProjectData;

        interface ProjectColorPalette extends DefaultProjectColors {
        }

        type SystemData = DefaultPalette["themes"]["dark"]["system"];
        type DefaultSystemColors = SystemData;

        interface SystemColorPalette extends DefaultSystemColors {
        }

        type ContentData = DefaultPalette["themes"]["dark"]["content"];
        type DefaultContentColors = ContentData;

        interface ContentColorPalette extends DefaultContentColors {
        }

        type CodeData = DefaultPalette["themes"]["dark"]["code"];
        type DefaultCodeColors = CodeData;

        interface CodeColorPalette extends DefaultCodeColors {
        }

        type ContainerContentColors = DefaultContentColors["container"];
        type BorderContentColors = DefaultContentColors["border"];
        type IconContentColors = DefaultContentColors["icon"];
        type TextContentColors = DefaultContentColors["text"];

        type DisabledSystemColors = DefaultSystemColors["disabled"];
        type StateSystemColors = DefaultSystemColors["state"];

        type Locales = Array<Locale>;

        interface Locale {
            rruleConfig?: GeneratedRRuleConfigs;
            translations?: Translation;
            locale: string;
            isRTL: boolean;
        }

        type DefaultLocalization = typeof defaultLocaleJSON[0];

        type GeneratedRRuleConfigsForReturn = {
            [K in keyof DefaultLocalization["rruleConfig"]]: DefaultLocalization["rruleConfig"][K];
        };

        type GeneratedRRuleConfigs = {
            [K in keyof DefaultLocalization["rruleConfig"]]?: DefaultLocalization["rruleConfig"][K];
        };

        type GeneratedTranslations = {
            [K in keyof DefaultLocalization["translations"]]?: DefaultLocalization["translations"][K];
        };

        interface Translation extends GeneratedTranslations {
        }

        type NavigationRoute = {
            params?: Record<string, unknown>;
            state?: NavigationState;
            name: string;
            key: string;
        };

        type NavigationState = {
            routes: Array<NavigationRoute>;
            index: number;
        };

        type Navigation = {
            addListener: (state: string, callback: () => void) => () => void;
            getRootState: () => NavigationState;
            navigate: (page: string, config?: {
                screen: string
            }) => void;
            getState: () => NavigationState;
            canGoBack: () => boolean;
            goBack: () => void;
        };
    }
}
