import { RTETextBlock } from './dto/blocks/text-block';
import { JSXBase } from '../../stencil-public-runtime';
import { RTEImageBlock } from './dto/blocks/image-block';
import { RTEListItemBlock } from './dto/blocks/list-item-block';
import { RTEListBlock } from './dto/blocks/list-block';
import { BlockAnnotation, BlockAnnotationTypeEnum } from './dto/annotations/block-annotation.abstract';
import { NodeAnnotation, NodeAnnotationTypeEnum } from './dto/annotations/node-annotation.abstract';
import { InternalAnnotationTypeEnum } from './dto/annotations/annotation.abstract';
import { CommonAnnotation, CommonAnnotationTypeEnum } from './dto/annotations/common-annotation.abstract';
import { SelectionRangeAnnotation } from './dto/annotations/selection-range-annotation';
import { VegaRichTextImageEditorSizeType } from './vega-rich-text-image-editor/types';
import { RTECodeBlock } from './dto/blocks/code-block';
import { VegaCodeBlockValue } from '../vega-code-block/types';
import { LinkGroupAnnotation } from './dto/annotations/link-group-annotation';
import { VNode } from '../../stencil-public-runtime';
import * as VegaComponents from '../../components';
import { RTEHtmlBlock } from './dto/blocks/html-block';
import { InlineHtmlAnnotation } from './dto/annotations/inline-html-annotation';
import { RTERange, RTERangeOptions } from './dto/range';
import type { RTENode } from './dto/nodes/node.abstract';
import type { VegaRTEContent } from './dto/content-state';

/**
 * Configuration for a toolbar button.
 */
export type ToolbarButtonConfig = {
	/**
	 * Icon name for the button.
	 */
	icon: string;
	/**
	 * Tooltip configuration for the button.
	 */
	tooltip: Partial<Pick<HTMLVegaTooltipElement, 'text'>>;
	/**
	 * Whether to focus the content when clicked
	 */
	autoFocusOnClick?: boolean;
};

/**
 * Inline style map used in annotations.
 */
export type AnnotationStyle = Record<string, string>;

/**
 * Text style variants supported by the editor.
 */
export type TableCellStylePropertiesMap = Record<string, RTETablePropertiesType>;

export type VegaRTETextStyleType =
	| 'title'
	| 'subtitle'
	| 'paragraph'
	| 'heading-1'
	| 'heading-2'
	| 'heading-3'
	| 'heading-4'
	| 'heading-5'
	| 'heading-6';

export type VegaRTETextStyleItem = {
	key: VegaRTETextStyleType;
};

/**
 * Heading block variants used in the editor.
 */
export type RTEHeadingBlockType =
	| 'heading-1'
	| 'heading-2'
	| 'heading-3'
	| 'heading-4'
	| 'heading-5'
	| 'heading-6';

/**
 * Text block variants used by the editor.
 */
export type VegaRTETextBlockType = 'title' | 'subtitle' | 'paragraph' | RTEHeadingBlockType | 'list-item';

/**
 * List block variants used by the editor.
 */
export type VegaRTEListBlockType = 'bullet-list' | 'number-list';

/**
 * Union of all supported block types.
 */
export type RTEBlockType =
	| VegaRTETextBlockType
	| VegaRTEListBlockType
	| 'image'
	| 'code-block'
	| 'html-block';

/**
 * Union of base content block models.
 */
export type RTEContentBlock =
	| RTETextBlock
	| RTEImageBlock
	| RTEListBlock
	| RTEListItemBlock
	| RTECodeBlock
	| RTEHtmlBlock;

/**
 * Union of annotation sets used by the editor.
 */
export type VegaRTEAnnotations =
	| VegaRTEBlockAnnotations
	| VegaRTETextAnnotations
	| VegaRTEImageAnnotations
	| VegaRTETextBlockAnnotations;

/**
 * Annotations applied to block-level content.
 */
export type VegaRTEBlockAnnotations = {
	/**
	 * Text alignment for the block.
	 */
	textAlign?: VegaRTEBlockAlignment;
	/**
	 * Indent level for the block.
	 */
	indent?: number;
	/**
	 * Custom attributes to attach to the block.
	 */
	customAttribute?: Record<string, string>;
	/**
	 * Custom CSS classes for the block.
	 */
	customClass?: string[];
	/**
	 * Inline styles for the block.
	 */
	customStyle?: AnnotationStyle;
	/**
	 * Whether to wrap the block with an internal container.
	 */
	internalWrapper?: boolean;
};

/**
 * Alias for list block variants.
 */
export type ListType = VegaRTEListBlockType;

//TODO: href should include to customAttribute.
/**
 * Link annotation data used in the editor.
 */
export type VegaRTELink = {
	/**
	 * Link target URL.
	 */
	href: string;
	/**
	 * Grouping key for link annotations.
	 */
	groupKey: string;
	/**
	 * Custom attributes for the link.
	 */
	customAttribute?: Record<string, string>;
	/**
	 * Custom CSS classes for the link.
	 */
	customClass?: string[];
	/**
	 * Inline styles for the link.
	 */
	customStyle?: AnnotationStyle;
};

/**
 * Inline text annotations used by the editor.
 */
export type VegaRTETextAnnotations = {
	/**
	 * Whether text is bold.
	 */
	bold?: boolean;
	/**
	 * Whether text is italic.
	 */
	italic?: boolean;
	/**
	 * Whether text is underlined.
	 */
	underline?: boolean;
	/**
	 * Whether text is struck through.
	 */
	strikethrough?: boolean;
	/**
	 * Text color value.
	 */
	textColor?: string;
	/**
	 * Optional link annotation.
	 */
	link?: VegaRTELink;
	/**
	 * Whether text is rendered as code.
	 */
	code?: boolean;
	/**
	 * Custom attributes for the text.
	 */
	customAttribute?: Record<string, string>;
	/**
	 * Custom CSS classes for the text.
	 */
	customClass?: string[];
	/**
	 * Inline styles for the text.
	 */
	customStyle?: AnnotationStyle;
	/**
	 * Inline HTML annotation schema.
	 */
	inlineHtml?: VegaInlineHtmlSchema;
	/**
	 * Whether the text should be treated as plain text.
	 */
	plainText?: boolean;
};

/**
 * Image annotation data used by the editor.
 */
export type VegaRTEImageAnnotations = {
	/**
	 * Image size variant.
	 */
	size?: VegaRichTextImageEditorSizeType;
	/**
	 * Alternate text for the image.
	 */
	alt?: string;
	/**
	 * Custom attributes for the image.
	 */
	customAttribute?: Record<string, string>;
	/**
	 * Custom CSS classes for the image.
	 */
	customClass?: string[];
	/**
	 * Inline styles for the image.
	 */
	customStyle?: AnnotationStyle;
};

/**
 * Text block annotations extending base block annotations.
 */
export type VegaRTETextBlockAnnotations = VegaRTEBlockAnnotations & {
	/**
	 * Text style for the block.
	 */
	textStyle?: VegaRTETextStyleType;
};

/**
 * Base node structure with identifier and type.
 */
export type VegaRTEBaseNode = {
	/**
	 * Unique node id.
	 */
	id: string;
	/**
	 * Node type identifier.
	 */
	type: string;
};

/**
 * Text node content with annotations.
 */
export type VegaRTEText = {
	/**
	 * Text content.
	 */
	text: string;
	/**
	 * Optional text annotations.
	 */
	annotations?: VegaRTETextAnnotations;
};

/**
 * Text node including base node metadata.
 */
export type VegaRTETextNode = VegaRTEBaseNode & VegaRTEText;

/**
 * Image node used within the editor.
 */
export type VegaRTEImageNode = {
	/**
	 * Unique node id.
	 */
	id: string;
	/**
	 * Node type identifier.
	 */
	type: 'image';
	/**
	 * Image URL.
	 */
	url: string;
	/**
	 * Optional image annotations.
	 */
	annotations?: VegaRTEImageAnnotations;
};

/**
 * Block alignment options.
 */
export type VegaRTEBlockAlignment = 'left' | 'center' | 'right' | 'justify';

/**
 * Image block structure.
 */
export type VegaRTEImageBlock = VegaRTEBlockBase & {
	/**
	 * Block type identifier.
	 */
	type: 'image';
	/**
	 * Image nodes contained in the block.
	 */
	nodes: VegaRTEImageNode[];
};

/**
 * Base interface for block nodes.
 */
export interface VegaRTEBlockBase {
	/**
	 * Unique block id.
	 */
	id: string;
	/**
	 * Optional block annotations.
	 */
	annotations?: VegaRTEBlockAnnotations;
}

/**
 * Text block node interface.
 */
export interface VegaRTETextBlock extends VegaRTEBlockBase {
	/**
	 * Block type identifier.
	 */
	type: VegaRTETextBlockType;
	/**
	 * Child text nodes.
	 */
	nodes: VegaRTETextNode[];
	/**
	 * Optional text block annotations.
	 */
	annotations?: VegaRTETextBlockAnnotations;
}

/**
 * List item block node.
 */
export type VegaRTEListItemBlock = VegaRTETextBlock & {
	/**
	 * Block type identifier.
	 */
	type: 'list-item';
	/**
	 * Optional nested list blocks.
	 */
	children?: VegaRTEListBlock[];
};

/**
 * List block node.
 */
export type VegaRTEListBlock = VegaRTEBlockBase & {
	/**
	 * Block type identifier.
	 */
	type: VegaRTEListBlockType;
	/**
	 * List item blocks contained in the list.
	 */
	blocks: VegaRTEListItemBlock[];
};

/**
 * Code block node.
 */
export type VegaRTECodeBlock = VegaRTEBlockBase & {
	/**
	 * Block type identifier.
	 */
	type: 'code-block';
	/**
	 * Code content.
	 */
	content: string;
	/**
	 * Optional language identifier for syntax highlighting.
	 */
	language?: VegaCodeBlockValue['language'];
};

/**
 * HTML block node.
 */
export type VegaRTEHtmlBlock = VegaRTEBlockBase & {
	/**
	 * Block type identifier.
	 */
	type: 'html-block';
	/**
	 * HTML tag name to render.
	 */
	htmlTag: string;
	/**
	 * Child content blocks.
	 */
	children: VegaRTEContentBlock[];
};

/**
 * Union of content nodes supported by the editor.
 */
export type VegaRTEContentNode = VegaRTETextNode | VegaRTEImageNode;

/**
 * Union of content block nodes supported by the editor.
 */
export type VegaRTEContentBlock =
	| VegaRTETextBlock
	| VegaRTEImageBlock
	| VegaRTEListBlock
	| VegaRTEListItemBlock
	| VegaRTECodeBlock
	| VegaRTECustomBlock
	| VegaRTEHtmlBlock;

/**
 * Toolbar item keys supported by the editor.
 */
export type VegaRTEToolbarItem =
	| 'clearStyle'
	| 'bold'
	| 'textStyles'
	| 'italic'
	| 'underline'
	| 'strikethrough'
	| 'code'
	| 'link'
	| 'moreIndent'
	| 'textColor'
	| 'lessIndent'
	| 'image'
	| 'bullets'
	| 'numbers'
	| 'bulletsNumbers'
	| 'horizontalAlignment'
	| 'leftAlign'
	| 'centerAlign'
	| 'rightAlign'
	| 'justified'
	| 'codeBlock'
	| string; // Custom toolbar item types can be added here

/**
 * Color schema used for text or background colors.
 */
export type VegaRTEColorSchema = {
	/**
	 * Schema key identifier.
	 */
	key: string;
	/**
	 * Light theme color value.
	 */
	light: string;
	/**
	 * Dark theme color value.
	 */
	dark: string;
};

/**
 * Keys used to map block annotations.
 */
export type RTEBlockAnnotationMapKey =
	| keyof typeof BlockAnnotationTypeEnum
	| InternalAnnotationTypeEnum.LINK_GROUP
	| keyof typeof CommonAnnotationTypeEnum;

/**
 * Values stored in the block annotation map.
 */
export type RTEBlockAnnotationMapValue = BlockAnnotation | LinkGroupAnnotation | CommonAnnotation;

/**
 * Keys used to map node annotations.
 */
export type RTENodeAnnotationMapKey =
	| keyof typeof NodeAnnotationTypeEnum
	| keyof typeof InternalAnnotationTypeEnum
	| keyof typeof CommonAnnotationTypeEnum;

/**
 * Values stored in the node annotation map.
 */
export type RTENodeAnnotationMapValue =
	| NodeAnnotation
	| SelectionRangeAnnotation
	| CommonAnnotation
	| InlineHtmlAnnotation;

/**
 * Image payload used when uploading images.
 */
export type VegaRichTextEditorImage = {
	/**
	 * Image file to upload.
	 */
	file: File;
	/**
	 * Callback invoked with the uploaded URL.
	 */
	sendBackUploadedURLCallback: (url: string) => void;
};

/**
 * Rendering options passed to the rich text renderer.
 */
export type RTERenderContext = {
	/**
	 * Whether the content is editable.
	 */
	editable?: boolean;
	/**
	 * If `true`, render using inline styles for standalone web pages.
	 * If `false`, use CSS classes for integration within the RTE content view.
	 */
	standalone?: boolean;
	/**
	 * Host rich text editor element reference.
	 */
	host?: HTMLVegaRichTextEditorElement;
} & Partial<Pick<VegaRTETransformOptions, 'autoMatchFormat'>>;

/**
 * Heading level values.
 */
export type HeadingLevel = 1 | 2 | 3;

/**
 * Custom attribute filtering for rendering.
 */
export type RTERenderCustomAttributes = {
	/**
	 * Attribute names to allow through during render.
	 */
	filterAttributes?: string[];
};

/**
 * Options controlling RTE content transformation.
 */
export type VegaRTETransformOptions = {
	/**
	 * If `true`, automatically match the format of the content to the RTE's internal format. Not used in the toHtml method.
	 */
	autoMatchFormat?: boolean;
	/**
	 * If `true`, skip custom style, class and attribute when generating annotations from HTML elements. Not used in the toHtml method.
	 */
	skipCustomAnnotations?: boolean;
	/**
	 * If `true`, filter inline styles when converting to HTML or refill inline styles when converting from HTML. Used in fromHtml and toHtml methods.
	 */
	filterInlineStyles?: boolean;
};

/**
 * Configuration for source edit mode.
 */
export type VegaRTESourceEditConfig = Partial<
	Pick<VegaRTETransformOptions, 'autoMatchFormat' | 'filterInlineStyles'>
>;

/**
 * Tokenized text node used for parsing.
 */
export type VegaRTETokenNode = VegaRTETextNode & {
	/**
	 * Token node type identifier.
	 */
	type: string;
	/**
	 * Token value.
	 */
	token: string;
};

/**
 * Render result returned from renderer helpers.
 */
export type VegaRTERenderResult = VNode & {
	/**
	 * A function that returns a VNode representing the container for child elements.
	 */
	childrenContainerGetter?: () => VNode;
};

/**
 * Action emitted by custom elements.
 */
export type VegaRTECustomElementAction = {
	/**
	 * Action type identifier.
	 */
	type: 'selected' | 'unSelected' | 'delete' | 'insertText';
};

/**
 * Custom block node used for extensions.
 */
export type VegaRTECustomBlock = VegaRTEBlockBase & {
	/**
	 * Custom block type identifier.
	 */
	type: string;
	/**
	 * Optional custom child nodes.
	 */
	children?: (VegaRTECustomNode | VegaRTECustomBlock)[];
};

/**
 * Custom node used for extensions.
 */
export type VegaRTECustomNode = VegaRTEBaseNode & {
	/**
	 * Additional custom properties.
	 */
	[key: string]: unknown;
};

/**
 * Renderable node type used in render helpers.
 */
export type VegaRTERenderNode = VegaRTERenderResult | string | number;

/**
 * Factory function used to create render elements.
 */
export type VegaRTECreateElementFunction = <
	T extends keyof VegaComponents.JSX.IntrinsicElements | keyof JSXBase.IntrinsicElements,
>(
	elementType: T,
	props?: T extends keyof VegaComponents.JSX.IntrinsicElements
		? VegaComponents.JSX.IntrinsicElements[T] | { [attrName: string]: unknown }
		: T extends keyof JSXBase.IntrinsicElements
		? JSXBase.IntrinsicElements[T] | { [attrName: string]: unknown }
		: null,
	children?: VegaRTERenderNode | VegaRTERenderNode[],
) => VegaRTERenderResult;

/**
 * Rendering context for custom toolbar items.
 */
export type VegaRTEToolbarRenderContext = {
	/**
	 * Host element reference.
	 */
	host: HTMLVegaRichTextEditorElement;
	/**
	 * Current selection range.
	 */
	rteRange: RTERange;
	/**
	 * Whether source edit mode is enabled.
	 */
	sourceEditMode: boolean;
};

/**
 * Inline HTML schema used for annotations.
 */
export type VegaInlineHtmlSchema = {
	/**
	 * HTML tag name.
	 */
	htmlTag: string;
	/**
	 * Optional nested inline HTML schema.
	 */
	child?: VegaInlineHtmlSchema;
	/**
	 * Custom attributes for the element.
	 */
	customAttribute?: Record<string, string>;
	/**
	 * Custom CSS classes for the element.
	 */
	customClass?: string[];
	/**
	 * Inline styles for the element.
	 */
	customStyle?: Record<string, string>;
	/**
	 * Grouping identifier — used at render time to merge adjacent text nodes
	 * that share the same outer wrapper back into a single HTML element.
	 * Assigned during fromHtml parsing.
	 */
	groupId?: string;
};

/**
 * Focus range state for a selected node.
 */
export type FocusNodeRangeState = {
	/**
	 * Starting node for the selection.
	 */
	startNode: RTENode;
	/**
	 * Character offset in the start node.
	 */
	startOffset: number;
};

/**
 * Context provided to RTE extension handlers.
 */
export type RTEExtensionContext = {
	/**
	 * Host rich text editor element.
	 */
	host: HTMLVegaRichTextEditorElement;
	/**
	 * Check if the editor is in source edit mode.
	 *
	 * @returns {boolean} - Whether the editor is in source edit mode.
	 */
	isSourceEditMode: () => boolean;
	/**
	 * Get the currently selected nodes in the editor.
	 *
	 * @returns {RTENode[]} - An array of currently selected RTENode objects.
	 */
	getSelectedNodes: () => RTENode[];
	/**
	 * Set the currently selected nodes in the editor.
	 *
	 * @param {RTENode[]} nodes - An array of RTENode objects to set as selected.
	 * @param {RTERangeOptions} [rangeOptions] - Optional range options to define the selection range.
	 */
	setSelectedNodes: (nodes: RTENode[], rangeOptions?: RTERangeOptions) => void;
	/**
	 * Get the current selection object.
	 *
	 * @returns {Selection} - The current Selection object.
	 */
	getSelection: () => Selection;
	/**
	 * Flush the editor value to the host. Auto focus the last node if autoFocusLastNode is true.
	 * Sometimes, the editor will lose focus after change the editor value, so we need to focus the last node again.
	 * Or apply the update cursor position action to focus the cursor to the specified position.
	 *
	 * @example flushValue(newValue, true);
	 * @example flushValue(newValue); host.value.apply(new UpdateCursorPositionAction(node, offset));
	 * @param {VegaRTEContent} value - The content value to flush.
	 * @param {boolean} autoFocusLastNode - Whether to auto-focus the last node after flushing.
	 */
	flushValue: (value: VegaRTEContent, autoFocusLastNode?: boolean) => void;
};

/**
 * Props passed to toolbar button renderers.
 */
export type RTEToolbarButtonProps = {
	/**
	 * Optional icon name.
	 */
	icon?: string;
	/**
	 * Optional label text.
	 */
	label?: string;
	/**
	 * Whether to display the arrow icon.
	 */
	showArrowIcon?: boolean;
};

/**
 * Dropdown item used in toolbar dropdowns.
 */
export type RTEDropdownListItem = {
	/**
	 * Unique key for the item.
	 */
	key: string;
	/**
	 * Display label for the item.
	 */
	label: string;
	/**
	 * Optional icon name.
	 */
	icon?: string;
	/**
	 * Optional custom attributes for rendering.
	 */
	customAttrs?: Record<string, string>;
};

/**
 * Dropdown group used in toolbar dropdowns.
 */
export type RTEDropdownListGroup = {
	/**
	 * Unique key for the group.
	 */
	key: string;
	/**
	 * Display label for the group.
	 */
	label: string;
	/**
	 * Child items or groups.
	 */
	children: (RTEDropdownListItem | RTEDropdownListGroup)[];
};

/**
 * Props for the toolbar dropdown component.
 */
export type RTEToolbarDropdownProps = {
	/**
	 * Dropdown source items.
	 */
	source?: (RTEDropdownListItem | RTEDropdownListGroup)[];
	/**
	 * Selection mode for the dropdown.
	 */
	selectType?: 'none' | 'single';
	/**
	 * Selected item key.
	 */
	selectedSourceKey?: string;
	/**
	 * Maximum dropdown height in pixels.
	 */
	maxHeight?: number;
	/**
	 * Dropdown alignment.
	 */
	alignment?: 'start' | 'center' | 'end';
};

/**
 * Map of language keys to rich text content.
 */
export type RTELanguageContentMap = Record<string, VegaRTEContent | VegaRTEContentBlock[] | undefined>;

/**
 * State used by the language extension.
 */
export type RTELanguageExtensionState = {
	/**
	 * Currently selected language key.
	 */
	selectedLanguage: string;
	/**
	 * Content map keyed by language.
	 */
	contentMap: RTELanguageContentMap;
};

export type RTETablePropertiesType = {
	width?: string;
	height?: string;
	borderStyle?: string;
	borderColor?: string;
	borderWidth?: string;
	textAlign?: 'left' | 'center' | 'right' | 'justify';
	backgroundColor?: string;
	verticalAlign?: 'top' | 'middle' | 'bottom';
	padding?: string;
};

export type RTEFilterInlineStylesResult = {
	styles?: AnnotationStyle;
	classNames?: string[];
};

export type VegaRTEGenerateStyleOptions = {
	/**
	 * If `true`, include font-face declarations for typography styles in the generated content style file.
	 */
	enableFontImports?: boolean;
};
