/*
 * Управляет пользовательским интерфейсом чата, включая ввод сообщений,
 * отображение истории и подсказки команд для взаимодействия с пользователем.
 */

import { ChatHistoryItem } from './models/ChatHistoryItem';

export class ChatPanel {
	container: HTMLElement;
	props: {
		chatHistory: ChatHistoryItem[];
		onSendMessage: (message: string, selectedModel?: string) => void;
		availableModels?: string[];
		selectedModel?: string;
	};
	chatHistory: ChatHistoryItem[];
	messageInput: HTMLDivElement;
	sendButton: HTMLButtonElement;
	suggestionsContainer: HTMLDivElement;
	modelSelectButton: HTMLButtonElement;
	modelDropdown: HTMLDivElement;
	selectedModel: string;

	constructor(
		container: HTMLElement,
		props: {
			chatHistory: ChatHistoryItem[];
			onSendMessage: (message: string, selectedModel?: string) => void;
			availableModels?: string[];
			selectedModel?: string;
		}
	) {
		this.container = container;
		this.props = props;
		this.chatHistory = props.chatHistory || [];
		this.selectedModel = props.selectedModel || 'gemini-2.5-flash';

		this.init();
	}

	init(): void {
		this.container.innerHTML = `
            <div class="llm-agent-chat-panel">
                <div class="chat-history" id="chat-history"></div>
                <div class="chat-input-container">
                    <div class="scroll-container">
                        <div 
                            contenteditable="true" 
                            data-testid="editor-input-main" 
                            class="message-input-editor" 
                            tabindex="0"
                            data-placeholder="Введите сообщение или команду (/)"
                        ></div>
                    </div>
                    <div class="chat-controls">
                        <div class="control-buttons-left">
                            <div class="model-select-container">
                                <button class="model-select-button" id="model-select-button">
                                    <span class="model-name" id="selected-model-name">${this.selectedModel}</span>
                                    <svg class="dropdown-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
                                        <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"></path>
                                    </svg>
                                </button>
                                <div class="model-dropdown" id="model-dropdown" style="display: none;"></div>
                            </div>
                        </div>
                        <div class="control-buttons-right">
                            <button class="submit-button" id="send-button" data-tooltip="Enter">
                                <span class="submit-text">⏎ Enter</span>
                            </button>
                        </div>
                    </div>
                    <div class="suggestions" id="suggestions" style="display: none;"></div>
                </div>
            </div>
        `;

		this.messageInput = this.container.querySelector('.message-input-editor') as HTMLDivElement;
		this.sendButton = this.container.querySelector('#send-button') as HTMLButtonElement;
		this.suggestionsContainer = this.container.querySelector('#suggestions') as HTMLDivElement;
		this.modelSelectButton = this.container.querySelector('#model-select-button') as HTMLButtonElement;
		this.modelDropdown = this.container.querySelector('#model-dropdown') as HTMLDivElement;

		this.setupEventListeners();
		this.renderHistory();
		this.updateModelDropdown();
		this.updatePlaceholder();
	}

	setupEventListeners(): void {
		this.sendButton.addEventListener('click', () => this.handleSend());

		this.messageInput.addEventListener('keydown', (e) => {
			if (e.key === 'Enter' && !e.shiftKey) {
				if (this.suggestionsContainer.style.display === 'block') {
					const firstSuggestion = this.suggestionsContainer.querySelector('.suggestion-item');
					if (firstSuggestion) {
						this.messageInput.textContent = firstSuggestion.textContent || '';
						this.hideSuggestions();
						e.preventDefault();
						return;
					}
				}
				this.handleSend();
				e.preventDefault();
			}
		});

		this.messageInput.addEventListener('input', () => {
			this.handleInput();
			this.updatePlaceholder();
		});

		this.messageInput.addEventListener('focus', () => {
			this.updatePlaceholder();
		});

		this.messageInput.addEventListener('blur', () => {
			this.updatePlaceholder();
		});

		// Model selection
		this.modelSelectButton.addEventListener('click', (e) => {
			e.stopPropagation();
			this.toggleModelDropdown();
		});

		// Close dropdown when clicking outside
		document.addEventListener('click', (e) => {
			if (!this.modelSelectButton.contains(e.target as Node) && !this.modelDropdown.contains(e.target as Node)) {
				this.modelDropdown.style.display = 'none';
			}
			if (!this.suggestionsContainer.contains(e.target as Node)) {
				this.hideSuggestions();
			}
		});
	}

	updatePlaceholder(): void {
		const isEmpty = this.messageInput.textContent?.trim() === '';
		const isFocused = document.activeElement === this.messageInput;

		if (isEmpty && !isFocused) {
			this.messageInput.classList.add('is-empty');
		} else {
			this.messageInput.classList.remove('is-empty');
		}
	}

	toggleModelDropdown(): void {
		const isVisible = this.modelDropdown.style.display === 'block';
		if (isVisible) {
			this.modelDropdown.style.display = 'none';
			return;
		}

		// Показываем дропдаун, чтобы получить его размеры и положение
		this.modelDropdown.style.display = 'block';

		const modelSelectButtonRect = this.modelSelectButton.getBoundingClientRect();
		const modelDropdownRect = this.modelDropdown.getBoundingClientRect();
		const viewportHeight = window.innerHeight || document.documentElement.clientHeight;

		// ----------------------------------------------- Секция логики позиционирования дропдауна ----------------------------------------------------
		// Определяем, достаточно ли места снизу
		const spaceBelow = viewportHeight - modelSelectButtonRect.bottom;
		// Определяем, достаточно ли места сверху
		const spaceAbove = modelSelectButtonRect.top;

		if (spaceBelow >= modelDropdownRect.height || spaceBelow >= spaceAbove) {
			// Открываем вниз, если есть достаточно места или места снизу больше
			this.modelDropdown.style.top = `${modelSelectButtonRect.height + 4}px`; // 4px отступ от кнопки
			this.modelDropdown.style.bottom = 'auto';
		} else {
			// Открываем вверх
			this.modelDropdown.style.bottom = `${modelSelectButtonRect.height + 4}px`; // 4px отступ от кнопки
			this.modelDropdown.style.top = 'auto';
		}
		this.modelDropdown.style.left = '0';
		this.modelDropdown.style.right = 'auto'; // Сброс right, чтобы left работал корректно
		// ----------------------------------------------- End of Секция логики позиционирования дропдауна ---------------------------------------------
	}

	updateModelDropdown(): void {
		if (!this.props.availableModels) return;

		this.modelDropdown.innerHTML = this.props.availableModels
			.map(
				(model) => `
				<div class="model-option" data-model="${model}">
					${model}
				</div>
			`
			)
			.join('');

		// Add event listeners to model options
		this.modelDropdown.querySelectorAll('.model-option').forEach((option) => {
			option.addEventListener('click', () => {
				const model = (option as HTMLElement).dataset.model;
				if (model) {
					this.setSelectedModel(model);
				}
			});
		});
	}

	setSelectedModel(model: string): void {
		this.selectedModel = model;
		const modelNameElement = this.container.querySelector('#selected-model-name');
		if (modelNameElement) {
			modelNameElement.textContent = model;
		}
		this.modelDropdown.style.display = 'none';
	}

	handleInput(): void {
		const value = this.messageInput.textContent || '';
		const commands = ['/help', '/imagine', '/analyze', '/subtitles_meet', '/subtitles_teams', '/summarize', '/chat'];

		if (value.startsWith('/')) {
			const filteredCommands = commands.filter((cmd) => cmd.startsWith(value.toLowerCase()));
			this.showSuggestions(filteredCommands);
		} else {
			this.hideSuggestions();
		}
	}

	showSuggestions(suggestions: string[]): void {
		if (suggestions.length === 0) {
			this.hideSuggestions();
			return;
		}

		this.suggestionsContainer.innerHTML = suggestions.map((suggestion) => `<div class="suggestion-item">${suggestion}</div>`).join('');

		this.suggestionsContainer.style.display = 'block';

		// Добавляем обработчики кликов на предложения
		this.suggestionsContainer.querySelectorAll('.suggestion-item').forEach((item) => {
			item.addEventListener('click', () => {
				this.messageInput.textContent = item.textContent || '';
				this.hideSuggestions();
				this.messageInput.focus();
			});
		});
	}

	hideSuggestions(): void {
		this.suggestionsContainer.style.display = 'none';
	}

	handleSend(): void {
		const message = this.messageInput.textContent?.trim() || '';
		if (message && this.props.onSendMessage) {
			this.props.onSendMessage(message, this.selectedModel);
			this.messageInput.textContent = '';
			this.updatePlaceholder();
			this.hideSuggestions();
		}
	}

	renderHistory(): void {
		const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
		historyContainer.innerHTML = this.chatHistory
			.map(
				(msg, index) => `
                <div class="message ${msg.role} message-type-${msg.type || 'default'} ">
					<div class="chat-meta">
						<div class="chat-sender-info">
							<div class="chat-message-icon">
								${
									msg.role === 'user'
										? `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>`
										: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bot"><path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path></svg>`
								}
							</div>
                    		<span class="chat-role-label">${this.getRoleLabel(msg.role)}</span>
						</div>
					</div>
					<div class="chat-message-content">${this.processMessageContent(msg.content)}</div>
                </div>
        `
			)
			.join('');

		// Прокручиваем к последнему сообщению
		if (this.chatHistory.length > 0) {
			setTimeout(() => {
				const lastMessage = historyContainer.lastElementChild as HTMLElement;
				if (lastMessage) {
					lastMessage.scrollIntoView({ behavior: 'smooth', block: 'end' });
				}
			}, 0);
		}
	}

	/**
	 * Возвращает удобочитаемую метку для роли сообщения.
	 * @param {string} role - Роль отправителя сообщения (например, 'user', 'assistant').
	 * @returns {string} Локализованная метка роли.
	 */
	getRoleLabel(role: string): string {
		switch (role) {
			case 'user':
				return 'Вы:';
			case 'assistant':
				return 'LLM Агент:';
			default:
				return `${role}:`;
		}
	}

	processMessageContent(content: string): string {
		// Простейшая обработка Markdown для изображений
		return content.replace(/<img([^>]*?)>/g, '<img$1 style="max-width: 100%; height: auto;">').replace(/\n/g, '<br>');
	}

	updateHistory(newHistory: ChatHistoryItem[]): void {
		this.chatHistory = newHistory;
		this.renderHistory();
	}

	updateAvailableModels(models: string[]): void {
		this.props.availableModels = models;
		this.updateModelDropdown();
	}

	destroy(): void {
		this.container.innerHTML = '';
	}
}
