import { App, Menu, MenuItem, Plugin, Modal, requestUrl, TFile, moment } from 'obsidian';
import { DEFAULT_SETTINGS, DiscourseSyncSettings, DiscourseSyncSettingsTab } from './config';
import * as yaml from 'yaml';
import { t, setLocale } from './i18n';
import { expandEmbeds } from './expand-embeds';

export default class DiscourseSyncPlugin extends Plugin {
	settings: DiscourseSyncSettings;
	activeFile: { 
		name: string; 
		content: string;
		postId?: number; // Post ID field
	};
	async onload() {
		// Set locale based on Obsidian's language setting
		setLocale(moment.locale());

		// Update locale when Obsidian's language changes
		this.registerEvent(
			this.app.workspace.on('window-open', () => {
				setLocale(moment.locale());
			})
		);

		await this.loadSettings();
		this.addSettingTab(new DiscourseSyncSettingsTab(this.app, this));
		this.registerEvent(
			this.app.workspace.on("file-menu", (menu, file: TFile) => {
				this.registerDirMenu(menu, file);
			}),
		);

		this.addCommand({
			id: "category-modal",
			name: t('PUBLISH_TO_DISCOURSE'),
			callback: () => {
				this.openCategoryModal();
			},
		});

		// Add command to open post in browser
		this.addCommand({
			id: "open-in-discourse",
			name: t('OPEN_IN_DISCOURSE'),
			callback: () => {
				this.openInDiscourse();
			},
		});

	}

	async loadSettings() {
		this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
	}

	async saveSettings() {
		await this.saveData(this.settings);
	}

	extractImageReferences(content: string): string[] {
		const regex = /!\[\[(.*?)(?:\|.*?)?\]\]/g;
		const matches = [];
		let match;
		while ((match = regex.exec(content)) !== null) {
			matches.push(match[1]);
		}
		return matches;
	}

	async uploadImages(imageReferences: string[]): Promise<string[]> {
		const imageUrls: string[] = [];
		for (const ref of imageReferences) {
			const filePath = this.app.metadataCache.getFirstLinkpathDest(ref, this.activeFile.name)?.path;
			if (filePath) {
				const abstractFile = this.app.vault.getAbstractFileByPath(filePath);
				if (abstractFile instanceof TFile) {
					try {
						const imgfile = await this.app.vault.readBinary(abstractFile);
						const boundary = genBoundary();
						const sBoundary = '--' + boundary + '\r\n';
						const imgForm = `${sBoundary}Content-Disposition: form-data; name="file"; filename="${abstractFile.name}"\r\nContent-Type: image/${abstractFile.extension}\r\n\r\n`;


						let body = '';
						body += `\r\n${sBoundary}Content-Disposition: form-data; name="type"\r\n\r\ncomposer\r\n`;
						body += `${sBoundary}Content-Disposition: form-data; name="synchronous"\r\n\r\ntrue\r\n`;

						const eBoundary = '\r\n--' + boundary + '--\r\n';
						const imgFormArray = new TextEncoder().encode(imgForm);
						const bodyArray = new TextEncoder().encode(body);
						const endBoundaryArray = new TextEncoder().encode(eBoundary);

						const formDataArray = new Uint8Array(imgFormArray.length + imgfile.byteLength + bodyArray.length + endBoundaryArray.length);
						formDataArray.set(imgFormArray, 0);
						formDataArray.set(new Uint8Array(imgfile), imgFormArray.length);
						formDataArray.set(bodyArray, imgFormArray.length + imgfile.byteLength);
						formDataArray.set(endBoundaryArray, imgFormArray.length + bodyArray.length + imgfile.byteLength);

						const url = `${this.settings.baseUrl}/uploads.json`;
						const headers = {
							"Api-Key": this.settings.apiKey,
							"Api-Username": this.settings.disUser,
							"Content-Type": `multipart/form-data; boundary=${boundary}`,
						};

						const response = await requestUrl({
							url: url,
							method: "POST",
							body: formDataArray.buffer,
							throw: false,
							headers: headers,
						});

						if (response.status == 200) {
							const jsonResponse = response.json;
							imageUrls.push(jsonResponse.short_url);
						} else {
							new NotifyUser(this.app, `Error uploading image: ${response.status}`).open();
						}
					} catch (error) {
						new NotifyUser(this.app, `Exception while uploading image: ${error}`).open();
					}
				} else {
					new NotifyUser(this.app, `File not found in vault: ${ref}`).open();
				}
			} else {
				new NotifyUser(this.app, `Unable to resolve file path for: ${ref}`).open();
			}
		}
		return imageUrls;
	}

	async postTopic(): Promise<{ message: string; error?: string }> {
		const url = `${this.settings.baseUrl}/posts.json`;
		const headers = {
			"Content-Type": "application/json",
			"Api-Key": this.settings.apiKey,
			"Api-Username": this.settings.disUser,
		}
		let content = this.activeFile.content;

		// Check if frontmatter contains post ID
		const frontMatter = this.getFrontMatter(content);
		const postId = frontMatter?.discourse_post_id;
		const topicId = frontMatter?.discourse_topic_id;
		
		// Filter out note properties section
		content = content.replace(/^---[\s\S]*?---\n/, '');

		const imageReferences = this.extractImageReferences(content);
		const imageUrls = await this.uploadImages(imageReferences);

		// 替换所有图片引用，包括带有属性的图片
		imageReferences.forEach((ref, index) => {
			// 使用正则表达式匹配包含属性的图片引用
			const regex = new RegExp(`!\\[\\[${ref.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?:\\|.*?)?\\]\\]`, 'g');
			const discoRef = `![${ref}](${imageUrls[index]})`;
			content = content.replace(regex, discoRef);
		});

		const isUpdate = postId !== undefined;
		
		if (isUpdate) {
			// For updating a post
			const postEndpoint = `${this.settings.baseUrl}/posts/${postId}`;
			const topicEndpoint = `${this.settings.baseUrl}/t/${topicId}`;
			
			// First update the post content
			try {
				const postResponse = await requestUrl({
					url: postEndpoint,
					method: "PUT",
					contentType: "application/json",
					body: JSON.stringify({
						raw: content,
						edit_reason: "Updated from Obsidian"
					}),
					headers,
					throw: false
				});
				
				if (postResponse.status !== 200) {
					return { 
						message: "Error", 
						error: `${t('UPDATE_FAILED')} (${postResponse.status})` 
					};
				}
				
				// Then update the topic (for title and tags)
				const topicResponse = await requestUrl({
					url: topicEndpoint,
					method: "PUT",
					contentType: "application/json",
					body: JSON.stringify({
						title: (frontMatter?.title ? frontMatter?.title : this.activeFile.name),
						tags: this.settings.selectedTags || []
					}),
					headers,
					throw: false
				});
				
				if (topicResponse.status === 200) {
					return { message: "Success" };
				} else {
					try {
						const errorResponse = topicResponse.json;
						if (errorResponse.errors && errorResponse.errors.length > 0) {
							return { 
								message: "Error",
								error: errorResponse.errors.join('\n')
							};
						}
						if (errorResponse.error) {
							return {
								message: "Error",
								error: errorResponse.error
							};
						}
					} catch (parseError) {
						return {
							message: "Error",
							error: `${t('UPDATE_FAILED')} (${topicResponse.status})`
						};
					}
				}
			} catch (error) {
				return { 
					message: "Error",
					error: `${t('UPDATE_FAILED')}: ${error.message || t('UNKNOWN_ERROR')}`
				};
			}
		} else {
			// For creating a new post
			try {
				const response = await requestUrl({
					url,
					method: "POST",
					contentType: "application/json",
					body: JSON.stringify({
						title: (frontMatter?.title ? frontMatter?.title : this.activeFile.name),
						raw: content,
						category: this.settings.category,
						tags: this.settings.selectedTags || []
					}),
					headers,
					throw: false
				});

				if (response.status === 200) {
					try {
						// Get new post ID and topic ID
						const responseData = response.json;
						if (responseData && responseData.id) {
							await this.updateFrontMatter(responseData.id, responseData.topic_id);
						} else {
							return {
								message: "Error",
								error: t('POST_ID_ERROR')
							};
						}
					} catch (error) {
						return {
							message: "Error",
							error: t('SAVE_POST_ID_ERROR')
						};
					}
					return { message: "Success" };
				} else {
					try {
						const errorResponse = response.json;
						if (errorResponse.errors && errorResponse.errors.length > 0) {
							return { 
								message: "Error",
								error: errorResponse.errors.join('\n')
							};
						}
						if (errorResponse.error) {
							return {
								message: "Error",
								error: errorResponse.error
							};
						}
					} catch (parseError) {
						return {
							message: "Error",
							error: `${t('PUBLISH_FAILED')} (${response.status})`
						};
					}
				}
			} catch (error) {
				return { 
					message: "Error",
					error: `${t('PUBLISH_FAILED')}: ${error.message || t('UNKNOWN_ERROR')}`
				};
			}
		}
		return { message: "Error", error: `${isUpdate ? t('UPDATE_FAILED') : t('PUBLISH_FAILED')}, ${t('TRY_AGAIN')}` };
	}

	// Get frontmatter data
	private getFrontMatter(content: string): any {
		const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
		if (fmMatch) {
			try {
				return yaml.parse(fmMatch[1]);
			} catch (e) {
				return null;
			}
		}
		return null;
	}

	// Update frontmatter, add post ID
	private async updateFrontMatter(postId: number, topicId: number) {
		try {
			// Get current active file
			const activeFile = this.app.workspace.getActiveFile();
			if (!activeFile) {
				return;
			}

			const content = await this.app.vault.read(activeFile);
			const fm = this.getFrontMatter(content);
			const discourseUrl = `${this.settings.baseUrl}/t/${topicId}`;
			
			let newContent: string;
			if (fm) {
				// Update existing frontmatter
				const updatedFm = { 
					...fm, 
					discourse_post_id: postId, 
					discourse_topic_id: topicId,
					discourse_url: discourseUrl
				};
				newContent = content.replace(/^---\n[\s\S]*?\n---\n/, `---\n${yaml.stringify(updatedFm)}---\n`);
			} else {
				// Add new frontmatter
				const newFm = { 
					discourse_post_id: postId, 
					discourse_topic_id: topicId,
					discourse_url: discourseUrl
				};
				newContent = `---\n${yaml.stringify(newFm)}---\n${content}`;
			}
			
			await this.app.vault.modify(activeFile, newContent);
			
			// 更新 activeFile 对象，确保它反映最新状态
			this.activeFile = {
				name: activeFile.basename,
				content: newContent,
				postId: postId
			};
		} catch (error) {
			return {
				message: "Error",
				error: t('UPDATE_FAILED')
			};
		}
	}

	private async fetchCategories() {
		const url = `${this.settings.baseUrl}/categories.json?include_subcategories=true`;
		const headers = {
			"Content-Type": "application/json",
			"Api-Key": this.settings.apiKey,
			"Api-Username": this.settings.disUser,
		};

		try {
			const response = await requestUrl({
				url: url,
				method: "GET",
				contentType: "application/json",
				headers,
			});


			const data = await response.json;
			const categories = data.category_list.categories;
			const allCategories = categories.flatMap((category: Category) => {
				const subcategories: { id: number; name: string }[] = category.subcategory_list?.map((sub: Subcategory) => ({
					id: sub.id,
					name: sub.name,
				})) || [];
				return [
					{ id: category.id, name: category.name },
					...subcategories,
				];
			});
			return allCategories;
		} catch (error) {
			return [];
		}
	}

	private async fetchTags(): Promise<{ name: string; canCreate: boolean }[]> {
		const url = `${this.settings.baseUrl}/tags.json`;
		const headers = {
			"Content-Type": "application/json",
			"Api-Key": this.settings.apiKey,
			"Api-Username": this.settings.disUser,
		};

		try {
			const response = await requestUrl({
				url: url,
				method: "GET",
				contentType: "application/json",
				headers,
			});

			if (response.status === 200) {
				const data = response.json;
				// Get user permissions
				const canCreateTags = await this.checkCanCreateTags();
				// Tags list returned by Discourse is in the tags array
				return data.tags.map((tag: any) => ({
					name: tag.name,
					canCreate: canCreateTags
				}));
			}
			return [];
		} catch (error) {
			return [];
		}
	}

	// Check if user has permission to create tags
	private async checkCanCreateTags(): Promise<boolean> {
		try {
			const url = `${this.settings.baseUrl}/u/${this.settings.disUser}.json`;
			const headers = {
				"Content-Type": "application/json",
				"Api-Key": this.settings.apiKey,
				"Api-Username": this.settings.disUser,
			};

			const response = await requestUrl({
				url: url,
				method: "GET",
				contentType: "application/json",
				headers,
			});

			if (response.status === 200) {
				const data = response.json;
				// Check user's trust_level
				return data.user.trust_level >= 3;
			}
			return false;
		} catch (error) {
			return false;
		}
	}

	/**
	 * 测试API密钥是否有效
	 * @returns 返回测试结果，包含成功状态和消息
	 */
	async testApiKey(): Promise<{ success: boolean; message: string }> {
		if (!this.settings.baseUrl || !this.settings.apiKey || !this.settings.disUser) {
			return { 
				success: false, 
				message: t('MISSING_CREDENTIALS') 
			};
		}

		const url = `${this.settings.baseUrl}/users/${this.settings.disUser}.json`;
		const headers = {
			"Content-Type": "application/json",
			"Api-Key": this.settings.apiKey,
			"Api-Username": this.settings.disUser,
		};

		try {
			const response = await requestUrl({
				url: url,
				method: "GET",
				contentType: "application/json",
				headers,
				throw: false
			});

			if (response.status === 200) {
				return { 
					success: true, 
					message: t('API_TEST_SUCCESS') 
				};
			} else {
				let errorMessage;
				try {
					const errorData = await response.json;
					errorMessage = errorData?.errors || errorData?.error || `${t('API_TEST_FAILED')} (${response.status})`;
				} catch (e) {
					errorMessage = `${t('API_TEST_FAILED')} (${response.status})`;
				}
				return { 
					success: false, 
					message: errorMessage 
				};
			}
		} catch (error) {
			return { 
				success: false, 
				message: error.message || t('UNKNOWN_ERROR')
			};
		}
	}

	registerDirMenu(menu: Menu, file: TFile) {
		const syncDiscourse = (item: MenuItem) => {
			item.setTitle(t('PUBLISH_TO_DISCOURSE'));
			item.onClick(async () => {
				const content = await expandEmbeds(this.app, file);
				const fm = this.getFrontMatter(content);
				this.activeFile = {
					name: file.basename,
					content: content,
					postId: fm?.discourse_post_id
				};
				await this.syncToDiscourse();
			});
		}
		menu.addItem(syncDiscourse)
	}

	private async openCategoryModal() {
		// 每次都重新获取 activeFile 的最新内容，不使用缓存
		const activeFile = this.app.workspace.getActiveFile();
		if (!activeFile) {
			new NotifyUser(this.app, t('NO_ACTIVE_FILE')).open();
			return;
		}
		
		const content = await this.app.vault.read(activeFile);
		const fm = this.getFrontMatter(content);
		this.activeFile = {
			name: activeFile.basename,
			content: content,
			postId: fm?.discourse_post_id
		};
		
		const [categories, tags] = await Promise.all([
			this.fetchCategories(),
			this.fetchTags()
		]);
		if (categories.length > 0) {
			new SelectCategoryModal(this.app, this, categories, tags).open();
		}
	}

	private async syncToDiscourse() {
		await this.openCategoryModal();
	}

	private async openInDiscourse() {
		const activeFile = this.app.workspace.getActiveFile();
		if (!activeFile) {
			new NotifyUser(this.app, t('NO_ACTIVE_FILE')).open();
			return;
		}

		const content = await this.app.vault.read(activeFile);
		const fm = this.getFrontMatter(content);
		const discourseUrl = fm?.discourse_url;
		const topicId = fm?.discourse_topic_id;

		if (!discourseUrl && !topicId) {
			new NotifyUser(this.app, t('NO_TOPIC_ID')).open();
			return;
		}

		const url = discourseUrl || `${this.settings.baseUrl}/t/${topicId}`;
		window.open(url, '_blank');
	}

	onunload() {}

}

interface Subcategory {
	id: number;
	name: string;
}

interface Category {
	id: number;
	name: string;
	subcategory_list?: Subcategory[];
}

const genBoundary = (): string => {
	return '----WebKitFormBoundary' + Math.random().toString(36).substring(2, 15);
}


export class NotifyUser extends Modal {
	message: string;
	constructor(app: App, message: string) {
		super(app);
		this.message = message;
	}

	onOpen() {
		const { contentEl } = this;
		contentEl.createEl("h1", { text: 'An error has occurred.' });
		contentEl.createEl("h4", { text: this.message });
		const okButton = contentEl.createEl('button', { text: 'Ok' });
		okButton.onclick = () => {
			this.close();
		}
	}

	onClose() {
		const { contentEl } = this;
		contentEl.empty();
	}

}

export class SelectCategoryModal extends Modal {
	plugin: DiscourseSyncPlugin;
	categories: {id: number; name: string}[];
	tags: { name: string; canCreate: boolean }[];
	canCreateTags = false;

	constructor(app: App, plugin: DiscourseSyncPlugin, categories: {id: number; name: string }[], tags: { name: string; canCreate: boolean }[]) {
		super(app);
		this.plugin = plugin;
		this.categories = categories;
		this.tags = tags;
		this.canCreateTags = tags.length > 0 ? tags[0].canCreate : false;
	}

	onOpen() {
		// Add modal base style
		this.modalEl.addClass('mod-discourse-sync');
		const { contentEl } = this;
		contentEl.empty();
		contentEl.addClass('discourse-sync-modal');

		// 确保activeFile存在
		if (!this.plugin.activeFile) {
			contentEl.createEl("h1", { text: t('ERROR') });
			contentEl.createEl("p", { text: t('NO_ACTIVE_FILE') });
			return;
		}

		const isUpdate = this.plugin.activeFile.postId !== undefined;
		contentEl.createEl("h1", { text: isUpdate ? t('UPDATE_POST') : t('PUBLISH_TO_DISCOURSE') });
		
		// Create form area container
		const formArea = contentEl.createEl('div', { cls: 'form-area' });
		
		// Create selector container
		const selectContainer = formArea.createEl('div', { cls: 'select-container' });
		if (!isUpdate) {
			// Only show category selector when creating a new post
			selectContainer.createEl('label', { text: t('CATEGORY') });
			const selectEl = selectContainer.createEl('select');
			this.categories.forEach(category => {
				const option = selectEl.createEl('option', { text: category.name });
				option.value = category.id.toString();
			});
		}

		// Create tag selector container
		const tagContainer = formArea.createEl('div', { cls: 'tag-container' });
		tagContainer.createEl('label', { text: t('TAGS') });
		
		// Create tag selector area
		const tagSelectArea = tagContainer.createEl('div', { cls: 'tag-select-area' });
		
		// Selected tags display area
		const selectedTagsContainer = tagSelectArea.createEl('div', { cls: 'selected-tags' });
		const selectedTags = new Set<string>();
		
		// Initialize with existing tags if updating
		if (isUpdate && this.plugin.settings.selectedTags && this.plugin.settings.selectedTags.length > 0) {
			this.plugin.settings.selectedTags.forEach(tag => selectedTags.add(tag));
		}

		// Update selected tags display
		const updateSelectedTags = () => {
			selectedTagsContainer.empty();
			selectedTags.forEach(tag => {
				const tagEl = selectedTagsContainer.createEl('span', { 
					cls: 'tag',
					text: tag
				});
				const removeBtn = tagEl.createEl('span', {
					cls: 'remove-tag',
					text: '×'
				});
				removeBtn.onclick = () => {
					selectedTags.delete(tag);
					updateSelectedTags();
				};
			});
		};
		
		// Initialize tag display
		updateSelectedTags();

		// Create tag input container
		const tagInputContainer = tagSelectArea.createEl('div', { cls: 'tag-input-container' });
		
		// Create tag input and suggestions
		const tagInput = tagInputContainer.createEl('input', {
			type: 'text',
			placeholder: this.canCreateTags ? t('ENTER_TAG_WITH_CREATE') : t('ENTER_TAG')
		});

		// Create tag suggestions container
		const tagSuggestions = tagInputContainer.createEl('div', { cls: 'tag-suggestions' });

		// Handle input event, show matching tags
		tagInput.oninput = () => {
			const value = tagInput.value.toLowerCase();
			tagSuggestions.empty();

			if (value) {
				const matches = this.tags
					.filter(tag => 
						tag.name.toLowerCase().includes(value) && 
						!selectedTags.has(tag.name)
					)
					.slice(0, 10);

				if (matches.length > 0) {
					// Get input box position and width
					const inputRect = tagInput.getBoundingClientRect();
					const modalRect = this.modalEl.getBoundingClientRect();
					
					// Ensure suggestions list doesn't exceed modal width
					const maxWidth = modalRect.right - inputRect.left - 24; // 24px is right padding
					
					// Set suggestions list position and width
					tagSuggestions.style.top = `${inputRect.bottom + 4}px`;
					tagSuggestions.style.left = `${inputRect.left}px`;
					tagSuggestions.style.width = `${Math.min(inputRect.width, maxWidth)}px`;

					matches.forEach(tag => {
						const suggestion = tagSuggestions.createEl('div', {
							cls: 'tag-suggestion',
							text: tag.name
						});
						suggestion.onclick = () => {
							selectedTags.add(tag.name);
							tagInput.value = '';
							tagSuggestions.empty();
							updateSelectedTags();
						};
					});
				}
			}
		};

		// Handle enter event
		tagInput.onkeydown = (e) => {
			if (e.key === 'Enter' && tagInput.value) {
				e.preventDefault();
				const value = tagInput.value.trim();
				if (value && !selectedTags.has(value)) {
					const existingTag = this.tags.find(t => t.name.toLowerCase() === value.toLowerCase());
					if (existingTag) {
						selectedTags.add(existingTag.name);
						updateSelectedTags();
					} else if (this.canCreateTags) {
						selectedTags.add(value);
						updateSelectedTags();
					} else {
						// Show permission notice
						const notice = contentEl.createEl('div', {
							cls: 'tag-notice',
							text: t('PERMISSION_ERROR')
						});
						setTimeout(() => {
							notice.remove();
						}, 2000);
					}
				}
				tagInput.value = '';
				tagSuggestions.empty();
			}
		};

		// Handle blur event, hide suggestions
		tagInput.onblur = () => {
			// Delay hide, so suggestions can be clicked
			setTimeout(() => {
				tagSuggestions.empty();
			}, 200);
		};

		// Handle window scroll, update suggestions list position
		const updateSuggestionsPosition = () => {
			if (tagSuggestions.childNodes.length > 0) {
				const inputRect = tagInput.getBoundingClientRect();
				tagSuggestions.style.top = `${inputRect.bottom + 4}px`;
				tagSuggestions.style.left = `${inputRect.left}px`;
				tagSuggestions.style.width = `${inputRect.width}px`;
			}
		};

		// Listen for scroll event
		this.modalEl.addEventListener('scroll', updateSuggestionsPosition);
		
		// Remove event listeners when modal closes
		this.modalEl.onclose = () => {
			this.modalEl.removeEventListener('scroll', updateSuggestionsPosition);
		};

		// Create button area
		const buttonArea = contentEl.createEl('div', { cls: 'button-area' });
		const submitButton = buttonArea.createEl('button', { 
			text: isUpdate ? t('UPDATE') : t('PUBLISH'),
			cls: 'submit-button'
		});

		// Create notice container
		const noticeContainer = buttonArea.createEl('div');
		
		submitButton.onclick = async () => {
			if (!isUpdate) {
				const selectEl = contentEl.querySelector('select') as HTMLSelectElement;
				if (!selectEl) {
					return;
				}
				const selectedCategoryId = selectEl.value;
				this.plugin.settings.category = parseInt(selectedCategoryId);
				await this.plugin.saveSettings();
			}
			
			// Save selected tags
			this.plugin.settings.selectedTags = Array.from(selectedTags);
			await this.plugin.saveSettings();
			
			// Disable submit button, show loading state
			submitButton.disabled = true;
			submitButton.textContent = isUpdate ? t('UPDATING') : t('PUBLISHING');
			
			try {
				const reply = await this.plugin.postTopic();
				
				// Show notice
				noticeContainer.empty();
				if (reply.message === 'Success') {
					noticeContainer.createEl('div', { 
						cls: 'notice success',
						text: isUpdate ? t('UPDATE_SUCCESS') : t('PUBLISH_SUCCESS')
					});
					// Close after success
					setTimeout(() => {
						this.close();
					}, 1500);
				} else {
					const errorContainer = noticeContainer.createEl('div', { cls: 'notice error' });
					errorContainer.createEl('div', { 
						cls: 'error-title',
						text: isUpdate ? t('UPDATE_ERROR') : t('PUBLISH_ERROR')
					});
					
					// Show Discourse-specific error information
					errorContainer.createEl('div', { 
						cls: 'error-message',
						text: reply.error || (isUpdate ? t('UPDATE_FAILED') + ', ' + t('TRY_AGAIN') : t('PUBLISH_FAILED') + ', ' + t('TRY_AGAIN'))
					});
					
					// Add retry button
					const retryButton = errorContainer.createEl('button', {
						cls: 'retry-button',
						text: t('RETRY')
					});
					retryButton.onclick = () => {
						noticeContainer.empty();
						submitButton.disabled = false;
						submitButton.textContent = isUpdate ? t('UPDATE') : t('PUBLISH');
					};
				}
			} catch (error) {
				noticeContainer.empty();
				const errorContainer = noticeContainer.createEl('div', { cls: 'notice error' });
				errorContainer.createEl('div', { 
					cls: 'error-title',
					text: isUpdate ? t('UPDATE_ERROR') : t('PUBLISH_ERROR')
				});
				errorContainer.createEl('div', { 
					cls: 'error-message',
					text: error.message || t('UNKNOWN_ERROR')
				});
				
				// Add retry button
				const retryButton = errorContainer.createEl('button', {
					cls: 'retry-button',
					text: t('RETRY')
				});
				retryButton.onclick = () => {
					noticeContainer.empty();
					submitButton.disabled = false;
					submitButton.textContent = isUpdate ? t('UPDATE') : t('PUBLISH');
				};
			}
			
			// If error occurs, reset button state
			if (submitButton.disabled) {
				submitButton.disabled = false;
				submitButton.textContent = isUpdate ? t('UPDATE') : t('PUBLISH');
			}
		};
	}

	onClose() {
		const { contentEl } = this;
		contentEl.empty();
	}
}
