class ChatSystem {
    constructor(config) {
        this.config = {
            wsUrl: config.wsUrl || 'ws://localhost:3001',
            apiUrl: config.apiUrl || '/api/chat',
            userType: config.userType,
            userId: config.userId,
            targetType: config.targetType,
            targetId: config.targetId,
            userName: config.userName,
            targetName: config.targetName,
            autoReconnect: true,
            reconnectDelay: 3000,
            maxReconnectAttempts: 5
        };
        
        this.ws = null;
        this.reconnectAttempts = 0;
        this.isConnected = false;
        this.isTyping = false;
        this.typingTimeout = null;
        this.lastTypingSent = 0;
        this.unreadCount = 0;
        this.messages = [];
        this.chatWindow = null;
        
        this.init();
    }
    
    init() {
        this.createChatUI();
        this.connectWebSocket();
        this.loadMessages();
        this.setupEventListeners();
    }
    
    createChatUI() {
        // Create FAB
        const fab = document.createElement('button');
        fab.className = 'chat-fab';
        fab.innerHTML = '<i class="fas fa-comment-dots"></i>';
        
        const badge = document.createElement('span');
        badge.className = 'chat-fab-badge';
        badge.style.display = 'none';
        fab.appendChild(badge);
        
        // Create chat window
        const chatWindow = document.createElement('div');
        chatWindow.className = 'chat-window';
        chatWindow.innerHTML = `
            <div class="chat-header">
                <div class="chat-header-info">
                    <div class="chat-avatar">
                        ${this.config.targetName ? this.config.targetName.charAt(0).toUpperCase() : 'U'}
                    </div>
                    <div class="chat-user-info">
                        <h4>${this.config.targetName || 'Chat'}</h4>
                        <span class="online-status offline" id="onlineStatus">Offline</span>
                    </div>
                </div>
                <button class="chat-close">
                    <i class="fas fa-times"></i>
                </button>
            </div>
            
            <div class="chat-body" id="chatBody">
                <div class="chat-loading">
                    <div class="chat-loading-spinner"></div>
                    <div>Loading messages...</div>
                </div>
            </div>
            
            <div class="chat-footer">
                <div class="chat-input-container">
                    <textarea 
                        class="chat-input" 
                        id="chatInput" 
                        placeholder="Type a message..."
                        rows="1"></textarea>
                    <button class="chat-send-btn" id="sendBtn">
                        <i class="fas fa-paper-plane"></i>
                    </button>
                </div>
            </div>
        `;
        
        document.body.appendChild(fab);
        document.body.appendChild(chatWindow);
        
        this.chatWindow = chatWindow;
        this.fab = fab;
        this.badge = badge;
        this.chatBody = chatWindow.querySelector('#chatBody');
        this.chatInput = chatWindow.querySelector('#chatInput');
        this.sendBtn = chatWindow.querySelector('#sendBtn');
        this.onlineStatus = chatWindow.querySelector('#onlineStatus');
        
        // FAB click handler
        fab.addEventListener('click', (e) => {
            e.stopPropagation();
            this.toggleChatWindow();
        });
        
        // Close button handler
        chatWindow.querySelector('.chat-close').addEventListener('click', () => {
            this.closeChatWindow();
        });
        
        // Close chat when clicking outside
        document.addEventListener('click', (e) => {
            if (!chatWindow.contains(e.target) && !fab.contains(e.target)) {
                this.closeChatWindow();
            }
        });
        
        // Auto-resize textarea
        this.chatInput.addEventListener('input', this.autoResizeTextarea.bind(this));
        
        // Send message on Enter (without Shift)
        this.chatInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                this.sendMessage();
            }
        });
        
        // Send button click
        this.sendBtn.addEventListener('click', () => this.sendMessage());
        
        // Typing detection
        this.chatInput.addEventListener('input', this.handleTyping.bind(this));
    }
    
    toggleChatWindow() {
        this.chatWindow.classList.toggle('active');
        if (this.chatWindow.classList.contains('active')) {
            this.markAllAsRead();
            this.scrollToBottom();
            this.chatInput.focus();
        }
    }
    
    closeChatWindow() {
        this.chatWindow.classList.remove('active');
    }
    
    autoResizeTextarea() {
        const textarea = this.chatInput;
        textarea.style.height = 'auto';
        textarea.style.height = Math.min(textarea.scrollHeight, 100) + 'px';
    }
    
    connectWebSocket() {
        try {
            this.ws = new WebSocket(this.config.wsUrl);
            
            this.ws.onopen = () => {
                console.log('WebSocket connected');
                this.isConnected = true;
                this.reconnectAttempts = 0;
                this.showConnectionStatus('connected');
                this.authenticate();
            };
            
            this.ws.onmessage = (event) => {
                this.handleMessage(event.data);
            };
            
            this.ws.onclose = () => {
                console.log('WebSocket disconnected');
                this.isConnected = false;
                this.showConnectionStatus('disconnected');
                
                if (this.config.autoReconnect && this.reconnectAttempts < this.config.maxReconnectAttempts) {
                    setTimeout(() => {
                        this.reconnectAttempts++;
                        console.log(`Reconnecting... Attempt ${this.reconnectAttempts}`);
                        this.connectWebSocket();
                    }, this.config.reconnectDelay);
                }
            };
            
            this.ws.onerror = (error) => {
                console.error('WebSocket error:', error);
                this.showConnectionStatus('disconnected');
            };
            
        } catch (error) {
            console.error('Failed to connect WebSocket:', error);
        }
    }
    
    showConnectionStatus(status) {
        // Remove existing status
        const existingStatus = document.querySelector('.connection-status');
        if (existingStatus) {
            existingStatus.remove();
        }
        
        if (status === 'connected') {
            return; // Don't show connected status, it's normal
        }
        
        const statusDiv = document.createElement('div');
        statusDiv.className = `connection-status ${status}`;
        
        if (status === 'disconnected') {
            statusDiv.textContent = 'Connection lost. Reconnecting...';
        } else if (status === 'connecting') {
            statusDiv.textContent = 'Connecting...';
        }
        
        document.body.appendChild(statusDiv);
        
        // Auto-remove after 5 seconds
        setTimeout(() => {
            if (statusDiv.parentNode) {
                statusDiv.remove();
            }
        }, 5000);
    }
    
    authenticate() {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
        
        const authData = {
            type: 'authenticate',
            userType: this.config.userType,
            userId: this.config.userId,
            adminId: this.config.userType === 'penghuni' ? this.config.targetId : null
        };
        
        this.ws.send(JSON.stringify(authData));
    }
    
    handleMessage(data) {
        try {
            const message = JSON.parse(data);
            
            switch (message.type) {
                case 'authenticated':
                    console.log('Authenticated successfully');
                    this.checkOnlineStatus();
                    break;
                    
                case 'message':
                    this.receiveMessage(message);
                    break;
                    
                case 'typing':
                    this.showTypingIndicator(message);
                    break;
                    
                case 'online_status':
                    this.updateOnlineStatus(message);
                    break;
                    
                case 'message_delivered':
                    this.updateMessageStatus(message.messageId, 'delivered');
                    break;
                    
                case 'read_receipt':
                    this.updateMessageStatus(message.messageId, 'read');
                    break;
                    
                case 'pong':
                    // Keep-alive response
                    break;
            }
        } catch (error) {
            console.error('Error parsing message:', error);
        }
    }
    
    async loadMessages() {
        try {
            const response = await fetch(
                `${this.config.apiUrl}/messages?` +
                `penghuni_id=${this.config.userType === 'penghuni' ? this.config.userId : this.config.targetId}` +
                `&admin_id=${this.config.userType === 'admin' ? this.config.userId : this.config.targetId}` +
                `&limit=50`
            );
            
            const data = await response.json();
            
            if (data.status) {
                this.messages = data.messages.reverse();
                this.renderMessages();
                this.updateUnreadCount();
            }
        } catch (error) {
            console.error('Failed to load messages:', error);
        }
    }
    
    renderMessages() {
        const chatBody = this.chatBody;
        chatBody.innerHTML = '';
        
        if (this.messages.length === 0) {
            chatBody.innerHTML = `
                <div class="chat-empty">
                    <i class="fas fa-comments"></i>
                    <p>No messages yet</p>
                    <p>Start the conversation!</p>
                </div>
            `;
            return;
        }
        
        this.messages.forEach(message => {
            const messageDiv = this.createMessageElement(message);
            chatBody.appendChild(messageDiv);
        });
        
        this.scrollToBottom();
    }
    
    createMessageElement(message) {
        const isSent = message.sender === this.config.userType;
        const messageDiv = document.createElement('div');
        messageDiv.className = `message ${isSent ? 'sent' : 'received'}`;
        messageDiv.dataset.messageId = message.id_chat;
        
        const time = new Date(message.created_at).toLocaleTimeString([], { 
            hour: '2-digit', 
            minute: '2-digit' 
        });
        
        messageDiv.innerHTML = `
            <div class="message-content">${this.escapeHtml(message.message)}</div>
            <div class="message-time">${time}</div>
        `;
        
        return messageDiv;
    }
    
    async sendMessage() {
        const message = this.chatInput.value.trim();
        if (!message || !this.isConnected) return;
        
        const messageId = 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
        
        // Create temporary message
        const tempMessage = {
            id_chat: messageId,
            message: message,
            sender: this.config.userType,
            created_at: new Date().toISOString(),
            is_delivered: 0,
            is_read: 0
        };
        
        this.messages.push(tempMessage);
        this.renderMessages();
        
        // Clear input
        this.chatInput.value = '';
        this.autoResizeTextarea();
        
        // Send via WebSocket
        const wsMessage = {
            type: 'message',
            from: {
                type: this.config.userType,
                id: this.config.userId,
                name: this.config.userName
            },
            to: {
                type: this.config.targetType,
                id: this.config.targetId,
                name: this.config.targetName
            },
            message: message,
            messageId: messageId,
            timestamp: new Date().toISOString()
        };
        
        this.ws.send(JSON.stringify(wsMessage));
        
        // Also send via HTTP API for persistence
        this.saveMessageToAPI(message, messageId);
        
        // Stop typing indicator
        this.sendTypingStatus(false);
    }
    
    async saveMessageToAPI(message, tempId) {
        try {
            const formData = new FormData();
            formData.append('id_penghuni', this.config.userType === 'penghuni' ? this.config.userId : this.config.targetId);
            formData.append('id_admin', this.config.userType === 'admin' ? this.config.userId : this.config.targetId);
            formData.append('message', message);
            formData.append('sender', this.config.userType);
            
            const response = await fetch(`${this.config.apiUrl}/messages`, {
                method: 'POST',
                body: formData
            });
            
            const data = await response.json();
            
            if (data.status) {
                // Replace temp ID with real ID
                const messageIndex = this.messages.findIndex(m => m.id_chat === tempId);
                if (messageIndex > -1) {
                    this.messages[messageIndex].id_chat = data.message_id;
                }
            }
        } catch (error) {
            console.error('Failed to save message:', error);
        }
    }
    
    receiveMessage(message) {
        const newMessage = {
            id_chat: message.messageId,
            message: message.message,
            sender: message.from.type,
            created_at: message.timestamp,
            is_delivered: 1,
            is_read: this.chatWindow.classList.contains('active') ? 1 : 0
        };
        
        this.messages.push(newMessage);
        this.renderMessages();
        
        if (!this.chatWindow.classList.contains('active')) {
            this.incrementUnreadCount();
            this.showNotification(message);
        } else {
            this.markMessageAsRead(newMessage.id_chat);
        }
        
        // Play notification sound
        this.playNotificationSound();
    }
    
    handleTyping() {
        const now = Date.now();
        if (now - this.lastTypingSent > 1000) { // Throttle to 1 second
            this.sendTypingStatus(true);
            this.lastTypingSent = now;
        }
        
        // Clear existing timeout
        if (this.typingTimeout) {
            clearTimeout(this.typingTimeout);
        }
        
        // Set timeout to stop typing indicator after 2 seconds of inactivity
        this.typingTimeout = setTimeout(() => {
            this.sendTypingStatus(false);
        }, 2000);
    }
    
    sendTypingStatus(isTyping) {
        if (!this.isConnected || this.isTyping === isTyping) return;
        
        this.isTyping = isTyping;
        
        const typingData = {
            type: 'typing',
            from: {
                type: this.config.userType,
                id: this.config.userId
            },
            to: {
                type: this.config.targetType,
                id: this.config.targetId
            },
            isTyping: isTyping
        };
        
        this.ws.send(JSON.stringify(typingData));
    }
    
    showTypingIndicator(message) {
        if (message.from.type !== this.config.targetType) return;
        
        const chatBody = this.chatBody;
        const existingTyping = chatBody.querySelector('.typing-indicator');
        
        if (message.isTyping) {
            if (!existingTyping) {
                const typingDiv = document.createElement('div');
                typingDiv.className = 'typing-indicator';
                typingDiv.innerHTML = `
                    <div class="typing-dot"></div>
                    <div class="typing-dot"></div>
                    <div class="typing-dot"></div>
                    <div class="typing-text">${this.config.targetName} is typing...</div>
                `;
                chatBody.appendChild(typingDiv);
                this.scrollToBottom();
            }
        } else {
            if (existingTyping) {
                existingTyping.remove();
            }
        }
    }
    
    updateOnlineStatus(message) {
        if (message.user.type === this.config.targetType && 
            message.user.id === this.config.targetId) {
            
            this.onlineStatus.textContent = message.isOnline ? 'Online' : 'Offline';
            this.onlineStatus.className = `online-status ${message.isOnline ? 'online' : 'offline'}`;
        }
    }
    
    async checkOnlineStatus() {
        try {
            const response = await fetch(
                `${this.config.apiUrl}/online_status?` +
                `user_type=${this.config.targetType}&user_id=${this.config.targetId}`
            );
            
            const data = await response.json();
            
            if (data.status) {
                this.onlineStatus.textContent = data.is_online ? 'Online' : 'Offline';
                this.onlineStatus.className = `online-status ${data.is_online ? 'online' : 'offline'}`;
            }
        } catch (error) {
            console.error('Failed to check online status:', error);
        }
    }
    
    updateMessageStatus(messageId, status) {
        const messageElement = this.chatBody.querySelector(`[data-message-id="${messageId}"]`);
        if (messageElement) {
            let statusText = '';
            if (status === 'delivered') statusText = '✓✓';
            if (status === 'read') statusText = '✓✓ Read';
            
            const statusDiv = document.createElement('div');
            statusDiv.className = 'message-status';
            statusDiv.textContent = statusText;
            
            const existingStatus = messageElement.querySelector('.message-status');
            if (existingStatus) {
                existingStatus.remove();
            }
            
            messageElement.appendChild(statusDiv);
        }
    }
    
    incrementUnreadCount() {
        this.unreadCount++;
        this.updateBadge();
    }
    
    updateUnreadCount() {
        // Count unread messages
        this.unreadCount = this.messages.filter(msg => 
            msg.sender === this.config.targetType && 
            msg.is_read === 0
        ).length;
        
        this.updateBadge();
    }
    
    updateBadge() {
        if (this.unreadCount > 0) {
            this.badge.textContent = this.unreadCount > 99 ? '99+' : this.unreadCount;
            this.badge.style.display = 'flex';
            
            // Add animation
            this.fab.style.animation = 'pulse 1s';
            setTimeout(() => {
                this.fab.style.animation = '';
            }, 1000);
        } else {
            this.badge.style.display = 'none';
        }
    }
    
    async markAllAsRead() {
        const unreadMessages = this.messages
            .filter(msg => msg.sender === this.config.targetType && msg.is_read === 0)
            .map(msg => msg.id_chat);
        
        if (unreadMessages.length === 0) return;
        
        try {
            const response = await fetch(`${this.config.apiUrl}/read`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    message_ids: unreadMessages,
                    reader_type: this.config.userType,
                    reader_id: this.config.userId
                })
            });
            
            const data = await response.json();
            
            if (data.status) {
                // Update local messages
                this.messages.forEach(msg => {
                    if (unreadMessages.includes(msg.id_chat)) {
                        msg.is_read = 1;
                    }
                });
                
                // Reset unread count
                this.unreadCount = 0;
                this.updateBadge();
                
                // Send read receipt via WebSocket
                if (this.isConnected) {
                    const readReceipt = {
                        type: 'read_receipt',
                        messageIds: unreadMessages,
                        reader: {
                            type: this.config.userType,
                            id: this.config.userId
                        },
                        chatPartner: {
                            type: this.config.targetType,
                            id: this.config.targetId
                        }
                    };
                    
                    this.ws.send(JSON.stringify(readReceipt));
                }
            }
        } catch (error) {
            console.error('Failed to mark as read:', error);
        }
    }
    
    markMessageAsRead(messageId) {
        if (!this.isConnected) return;
        
        const readReceipt = {
            type: 'read_receipt',
            messageId: messageId,
            reader: {
                type: this.config.userType,
                id: this.config.userId
            },
            chatPartner: {
                type: this.config.targetType,
                id: this.config.targetId
            }
        };
        
        this.ws.send(JSON.stringify(readReceipt));
    }
    
    showNotification(message) {
        // Check if browser supports notifications
        if (!("Notification" in window)) return;
        
        // Check if permission is granted
        if (Notification.permission === "granted") {
            this.createNotification(message);
        } else if (Notification.permission !== "denied") {
            Notification.requestPermission().then(permission => {
                if (permission === "granted") {
                    this.createNotification(message);
                }
            });
        }
    }
    
    createNotification(message) {
        const notification = new Notification(this.config.targetName, {
            body: message.message.length > 50 ? 
                  message.message.substring(0, 50) + '...' : 
                  message.message,
            icon: '/asset/img/notification-icon.png',
            badge: '/asset/img/notification-badge.png'
        });
        
        notification.onclick = () => {
            window.focus();
            this.toggleChatWindow();
            notification.close();
        };
        
        setTimeout(() => notification.close(), 5000);
    }
    
    playNotificationSound() {
        // Create audio element for notification sound
        const audio = new Audio('<?= base_url("asset/sounds/notification.mp3") ?>');
        audio.volume = 0.3;
        
        // Try to play, but don't worry if it fails (user might have blocked audio)
        audio.play().catch(() => {
            // Silent fail - audio play blocked
        });
    }
    
    scrollToBottom() {
        if (this.chatBody) {
            this.chatBody.scrollTop = this.chatBody.scrollHeight;
        }
    }
    
    escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }
}

// Initialize chat system when page loads
document.addEventListener('DOMContentLoaded', function() {
    // Only initialize on dashboard pages
    const isDashboard = window.location.pathname.includes('dashboard');
    if (!isDashboard) return;
    
    // Get user info from page or session
    const userType = document.body.dataset.userType || 'penghuni';
    const userId = document.body.dataset.userId || 0;
    const userName = document.body.dataset.userName || 'User';
    
    // For admin dashboard, we need to handle multiple users
    // For user dashboard, chat is always with their admin
    
    if (userType === 'penghuni') {
        // User chat - get admin info
        const adminId = document.body.dataset.adminId || 0;
        const adminName = document.body.dataset.adminName || 'Admin';
        
        window.chatSystem = new ChatSystem({
            wsUrl: 'ws://localhost:3001',
            apiUrl: '/api/chat',
            userType: 'penghuni',
            userId: userId,
            targetType: 'admin',
            targetId: adminId,
            userName: userName,
            targetName: adminName
        });
    } else if (userType === 'admin') {
        // Admin chat - will be initialized per user when chat button is clicked
        window.adminChatSystem = {
            userType: 'admin',
            userId: userId,
            userName: userName,
            activeChats: new Map(),
            
            startChatWithUser: function(penghuniId, penghuniName) {
                const chatKey = `chat_${penghuniId}`;
                
                if (!this.activeChats.has(chatKey)) {
                    const chatSystem = new ChatSystem({
                        wsUrl: 'ws://localhost:3001',
                        apiUrl: '/api/chat',
                        userType: 'admin',
                        userId: this.userId,
                        targetType: 'penghuni',
                        targetId: penghuniId,
                        userName: this.userName,
                        targetName: penghuniName
                    });
                    
                    this.activeChats.set(chatKey, chatSystem);
                }
                
                const chatSystem = this.activeChats.get(chatKey);
                chatSystem.toggleChatWindow();
                
                return chatSystem;
            }
        };
    }
});