// extensions/customMarks.ts
import {
	Mark,
	markInputRule,
	markPasteRule,
	mergeAttributes,
} from "@tiptap/core";

// Define available size options
const sizeOptions = {
	xs: "text-xs",
	sm: "text-sm",
	base: "text-base",
	lg: "text-lg",
	xl: "text-xl",
} as const;

export type SizeOption = keyof typeof sizeOptions;

export interface FontSizeOptions {
	HTMLAttributes: Record<string, any>;
}

declare module "@tiptap/core" {
	interface Commands<ReturnType> {
		fontSize: {
			setFontSize: (attributes: { size: SizeOption }) => ReturnType;
			toggleFontSize: (attributes: { size: SizeOption }) => ReturnType;
			unsetFontSize: () => ReturnType;
		};
	}
}

export const fontSizeInputRegex = /(?:^|\s)(~((?:[^~]+))~)$/;
export const fontSizePasteRegex = /(?:^|\s)(~((?:[^~]+))~)/g;

export const FontSize = Mark.create<FontSizeOptions>({
	name: "fontSize",

	addOptions() {
		return {
			HTMLAttributes: {},
		};
	},

	addAttributes() {
		return {
			size: {
				default: "base",
				parseHTML: (element: HTMLElement) => {
					const sizeClass = Object.entries(sizeOptions).find(
						([, className]) =>
							element.classList.contains(className),
					)?.[0];
					return sizeClass || "base";
				},
				renderHTML: (attributes: { size: SizeOption }) => ({
					class: sizeOptions[attributes.size],
				}),
			},
		};
	},

	parseHTML() {
		return [
			{
				tag: "span",
				getAttrs: (node: HTMLElement) => {
					const hasSizeClass = Object.values(sizeOptions).some(
						(className) => node.classList.contains(className),
					);
					return hasSizeClass ? {} : null;
				},
			},
		];
	},

	renderHTML({ HTMLAttributes }) {
		return [
			"span",
			mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
			0,
		];
	},

	addCommands() {
		return {
			setFontSize:
				(attributes: { size: SizeOption }) =>
				({ commands }) => {
					return commands.setMark(this.name, attributes);
				},
			toggleFontSize:
				(attributes: { size: SizeOption }) =>
				({ commands }) => {
					return commands.toggleMark(this.name, attributes);
				},
			unsetFontSize:
				() =>
				({ commands }) => {
					return commands.unsetMark(this.name);
				},
		};
	},

	addKeyboardShortcuts() {
		return {
			"Mod-s": () => this.editor.commands.toggleFontSize({ size: "sm" }),
		};
	},

	addInputRules() {
		return [
			markInputRule({
				find: fontSizeInputRegex,
				type: this.type,
				getAttributes: { size: "sm" }, // Default size for input rule
			}),
		];
	},

	addPasteRules() {
		return [
			markPasteRule({
				find: fontSizePasteRegex,
				type: this.type,
				getAttributes: { size: "sm" }, // Default size for paste rule
			}),
		];
	},
});

// TextColor remains unchanged
export interface TextColorOptions {
	HTMLAttributes: Record<string, any>;
}

declare module "@tiptap/core" {
	interface Commands<ReturnType> {
		textColor: {
			setTextColor: (attributes: { color: string }) => ReturnType;
			toggleTextColor: (attributes: { color: string }) => ReturnType;
			unsetTextColor: () => ReturnType;
		};
	}
}

export const TextColor = Mark.create<TextColorOptions>({
	name: "textColor",
	addOptions() {
		return {
			HTMLAttributes: {},
		};
	},
	addAttributes() {
		return {
			color: {
				default: null,
				parseHTML: (element: HTMLElement) => {
					const colorClass = Array.from(element.classList).find(
						(cls) => cls.startsWith("text-"),
					);
					return colorClass ? colorClass.replace("text-", "") : null;
				},
				renderHTML: (attributes) => {
					if (!attributes.color) return {};
					// Use !important to override prose styles
					return {
						class: `text-${attributes.color} !text-${attributes.color}`,
					};
				},
			},
		};
	},
	parseHTML() {
		return [
			{
				tag: "span",
				getAttrs: (node: HTMLElement) => {
					const colorClass = Array.from(node.classList).find((cls) =>
						cls.startsWith("text-"),
					);
					return colorClass
						? { color: colorClass.replace("text-", "") }
						: null;
				},
			},
		];
	},
	renderHTML({ HTMLAttributes }) {
		return [
			"span",
			mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
			0,
		];
	},
	addCommands() {
		return {
			setTextColor:
				(attributes: { color: string }) =>
				({ commands }) => {
					return commands.setMark(this.name, attributes);
				},
			toggleTextColor:
				(attributes: { color: string }) =>
				({ commands }) => {
					return commands.toggleMark(this.name, attributes);
				},
			unsetTextColor:
				() =>
				({ commands }) => {
					return commands.unsetMark(this.name);
				},
		};
	},
	addKeyboardShortcuts() {
		return {
			"Mod-Shift-c": () =>
				this.editor.commands.toggleTextColor({ color: "gray-500" }),
		};
	},
});
