import type { ComponentType } from "react";
import type { BundledTheme } from "shiki";

type LiveCodeBlockThemeNames = BundledTheme;
type StaticCodeBlockThemeNames = BundledTheme;

// Theme Type with all optional properties
export interface Theme {
    appearance?: "light" | "dark";
    backgroundColor?: CSSStyleDeclaration["backgroundColor"];
    fontFamily?: CSSStyleDeclaration["fontFamily"];
    customFontUrl?: string;
    titleColor?: CSSStyleDeclaration["color"];
    textColor?: CSSStyleDeclaration["color"];
    linkColor?: CSSStyleDeclaration["color"];
    linkHoverColor?: CSSStyleDeclaration["color"];
    linkUnderline?: boolean;
    tocFontFamily?: CSSStyleDeclaration["fontFamily"];
    tocCustomFontUrl?: string;
    tocColor?: CSSStyleDeclaration["color"];
    tocHoverColor?: CSSStyleDeclaration["color"];
    tocUnderline?: boolean;
    codeColor?: CSSStyleDeclaration["color"];
    codeBackgroundColor?: CSSStyleDeclaration["backgroundColor"];
    codeHeaderColor?: CSSStyleDeclaration["backgroundColor"];
    codeFontSize?: CSSStyleDeclaration["fontSize"];
    codeCopyButtonHoverColor?: CSSStyleDeclaration["color"];
    staticCodeTheme?: StaticCodeBlockThemeNames;
    liveCodeTheme?: LiveCodeBlockThemeNames;
    collapseSectionColor?: CSSStyleDeclaration["color"];
    katexSize?: CSSStyleDeclaration["fontSize"];
    tableBorderColor?: CSSStyleDeclaration["borderColor"];
    tableBackgroundColor?: CSSStyleDeclaration["backgroundColor"];
    captionColor?: CSSStyleDeclaration["color"];
    subtitleColor?: CSSStyleDeclaration["color"];
    tikZstyle?: "inverted" | "default";
    blockquoteStyle?: "default" | "latex";
    numberedHeading?: boolean;
    tocMarker?: boolean;
}

// NotieConfig Type with all optional properties
export interface NotieConfig {
    showTableOfContents?: boolean;
    previewEquations?: boolean;
    previewBlockquotes?: boolean;
    tocTitle?: string;
    fontSize?: CSSStyleDeclaration["fontSize"];
    /** Base URL of the code-runner service used by executable code blocks. */
    codeRunnerUrl?: string;
    /**
     * Desmos calculator API key used by ```desmos code blocks. Defaults to
     * the built-in demo key, which logs a warning that it is not licensed
     * for commercial use.
     */
    desmosApiKey?: string;
    theme?: Theme;
}

// NotieThemes consists of the string literals of the predefined themes
export type NotieThemes =
    | "default"
    | "default dark"
    | "Starlit Eclipse"
    | "Starlit Eclipse Light";

/**
 * Props passed to a custom component rendered from a ```component code
 * block. `config` is the full parsed JSON object from the code block
 * (including `componentName`). Zero-prop legacy components
 * (`() => JSX.Element`) remain compatible and simply ignore it.
 */
export interface CustomComponentProps {
    config?: Record<string, unknown>;
}

/**
 * Map from `componentName` (as referenced in ```component code blocks) to
 * the React component that renders it.
 */
export type CustomComponents = Record<
    string,
    ComponentType<CustomComponentProps>
>;

// FullTheme and FullNotieConfig are the types that are used in notie
export type FullTheme = Required<Theme>;
export type FullNotieConfig = Required<{
    [K in keyof NotieConfig]: K extends "theme" ? FullTheme : NotieConfig[K];
}>;
