/**
 * @file main.js
 * @description The main entry point for the web application.
 * This file imports all necessary modules, sets up the application structure,
 * initializes components, and establishes the WebSocket connection.
 */

// --- Stylesheets ---
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import './style.css';

// --- Module Imports -- -
import {StatusMessage} from './proto.js';
import * as api from './api.js';
import {initWebSocket} from './websocket.js';
import {setupTerminal, term} from './terminal.js';
import {
    applyTheme,
    initUI,
    updateControlStatus,
    updateSensorUI,
    updateSwitchStatusUI,
    updateUptimeUI,
    updateVersionUI,
    updateWebsocketStatus,
    updateWifiStatusUI
} from './ui.js';
import {setupEventListeners} from './events.js';

// --- Globals ---
// StatusMessage is imported directly from the generated proto.js file.

// --- DOM Elements ---
const loginContainer = document.getElementById('login-container');
const mainContent = document.querySelector('main.container');
const loginForm = document.getElementById('login-form');
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
const loginAlert = document.getElementById('login-alert');
const logoutButton = document.getElementById('logout-button');
const themeToggleLogin = document.getElementById('theme-toggle-login');
const themeIconLogin = document.getElementById('theme-icon-login');
const themeToggleMain = document.getElementById('theme-toggle');
const themeIconMain = document.getElementById('theme-icon');

// User Settings DOM Elements
const userSettingsForm = document.getElementById('user-settings-form');
const newUsernameInput = document.getElementById('new-username');
const newPasswordInput = document.getElementById('new-password');
const confirmPasswordInput = document.getElementById('confirm-password');


// --- WebSocket Event Handlers ---

function onWsOpen() {
    updateWebsocketStatus(true);
    console.log('Connected to WebSocket Server');
}

function onWsClose() {
    updateWebsocketStatus(false);
    console.warn('Connection closed. Reconnecting...');
    setTimeout(connect, 2000);
}

/**
 * Callback for when a message is received from the WebSocket server.
 * @param {MessageEvent} event - The WebSocket message event.
 */
function onWsMessage(event) {
    if (!(event.data instanceof ArrayBuffer)) {
        console.warn('Message is not an ArrayBuffer, skipping protobuf decoding.');
        return;
    }

    const buffer = new Uint8Array(event.data);
    try {
        const decodedMessage = StatusMessage.decode(buffer);
        const payloadType = decodedMessage.payload;

        switch (payloadType) {
            case 'sensorData': {
                const sensorData = decodedMessage.sensorData;
                if (sensorData) {
                    // Create a payload for the sensor UI (charts and header)
                    const sensorPayload = {
                        USB: sensorData.usb,
                        MAIN: sensorData.main,
                        VIN: sensorData.vin,
                        timestamp: sensorData.timestamp
                    };
                    updateSensorUI(sensorPayload);

                    // Update uptime separately from the sensor data payload
                    if (sensorData.uptimeSec !== undefined) {
                        updateUptimeUI(sensorData.uptimeSec);
                    }
                }
                break;
            }

            case 'wifiStatus':
                updateWifiStatusUI(decodedMessage.wifiStatus);
                break;

            case 'swStatus':
                if (decodedMessage.swStatus) {
                    updateSwitchStatusUI(decodedMessage.swStatus);
                }
                break;

            case 'uartData':
                if (term && decodedMessage.uartData && decodedMessage.uartData.data) {
                    term.write(decodedMessage.uartData.data);
                }
                break;

            default:
                if (payloadType !== undefined) {
                    console.warn('Received message with unknown or empty payload type:', payloadType);
                }
                break;
        }
    } catch (e) {
        console.error('Error decoding protobuf message:', e);
    }
}

// --- Authentication Functions ---

function checkAuth() {
    const token = localStorage.getItem('authToken');
    if (token) {
        return true;
    } else {
        return false;
    }
}

async function handleLogin(event) {
    event.preventDefault();
    const username = usernameInput.value;
    const password = passwordInput.value;

    try {
        const response = await api.login(username, password);
        if (response && response.token) {
            localStorage.setItem('authToken', response.token);
            loginAlert.classList.add('d-none');
            loginContainer.style.setProperty('display', 'none', 'important');
            initializeMainAppContent(); // After successful login, initialize the main app
        } else {
            loginAlert.textContent = 'Login failed: No token received.';
            loginAlert.classList.remove('d-none');
        }
    } catch (error) {
        console.error('Login error:', error);
        loginAlert.textContent = `Login failed: ${error.message}`;
        loginAlert.classList.remove('d-none');
    }
}

function handleLogout() {
    localStorage.removeItem('authToken');
    // Hide main content and show login form
    loginContainer.style.setProperty('display', 'flex', 'important');
    mainContent.style.setProperty('display', 'none', 'important');
    // Optionally, disconnect WebSocket or perform other cleanup
    // For now, just hide the main content.
}

// --- User Settings Functions ---
async function handleUserSettingsSubmit(event) {
    event.preventDefault();

    const newUsername = newUsernameInput.value;
    const newPassword = newPasswordInput.value;
    const confirmPassword = confirmPasswordInput.value;

    if (!newUsername || !newPassword || !confirmPassword) {
        alert('Please fill in all fields for username and password.');
        return;
    }

    if (newPassword !== confirmPassword) {
        alert('New password and confirm password do not match.');
        return;
    }

    try {
        const response = await api.updateUserSettings(newUsername, newPassword);
        if (response && response.status === 'user_credentials_updated') {
            alert('Username and password updated successfully. Please log in again with new credentials.');
            handleLogout(); // Force logout to re-authenticate with new credentials
        } else {
            alert(`Failed to update credentials: ${response.message || 'Unknown error'}`);
        }
    } catch (error) {
        console.error('Error updating user settings:', error);
        alert(`Error updating user settings: ${error.message}`);
    }
}

// --- Theme Toggle Functions ---
function setupThemeToggles() {
    // Initialize theme for login page
    const savedTheme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
    applyTheme(savedTheme);
    themeToggleLogin.checked = savedTheme === 'dark';
    themeIconLogin.className = savedTheme === 'dark' ? 'bi bi-moon-stars-fill' : 'bi bi-sun-fill';

    // Sync main theme toggle with login theme toggle (initial state)
    themeToggleMain.checked = savedTheme === 'dark';
    themeIconMain.className = savedTheme === 'dark' ? 'bi bi-moon-stars-fill' : 'bi bi-sun-fill';

    themeToggleLogin.addEventListener('change', () => {
        const newTheme = themeToggleLogin.checked ? 'dark' : 'light';
        applyTheme(newTheme);
        localStorage.setItem('theme', newTheme);
        themeIconLogin.className = newTheme === 'dark' ? 'bi bi-moon-stars-fill' : 'bi bi-sun-fill';
        themeToggleMain.checked = themeToggleLogin.checked; // Keep main toggle in sync
        themeIconMain.className = themeIconLogin.className; // Keep main icon in sync
    });

    themeToggleMain.addEventListener('change', () => {
        const newTheme = themeToggleMain.checked ? 'dark' : 'light';
        applyTheme(newTheme);
        localStorage.setItem('theme', newTheme);
        themeIconMain.className = newTheme === 'dark' ? 'bi bi-moon-stars-fill' : 'bi bi-sun-fill';
        themeToggleLogin.checked = themeToggleMain.checked; // Keep login toggle in sync
        themeIconLogin.className = themeIconMain.className; // Keep login icon in sync
    });
}


// --- Application Initialization ---

async function initializeVersion() {
    try {
        const versionData = await api.fetchVersion();
        if (versionData && versionData.version) {
            updateVersionUI(versionData.version);
        }
    } catch (error) {
        console.error('Error fetching version:', error);
        updateVersionUI('N/A');
    }
}

function connect() {
    updateControlStatus();
    initWebSocket({ onOpen: onWsOpen, onClose: onWsClose, onMessage: onWsMessage });
}

// New function to initialize main app content after successful login or on initial load if authenticated
function initializeMainAppContent() {
    loginContainer.style.setProperty('display', 'none', 'important');
    mainContent.style.setProperty('display', 'block', 'important');

    initUI();
    setupTerminal();
    initializeVersion();
    setupEventListeners(); // Attach main app event listeners
    logoutButton.addEventListener('click', handleLogout); // Attach logout listener
    connect();

    // Attach user settings form listener
    if (userSettingsForm) {
        userSettingsForm.addEventListener('submit', handleUserSettingsSubmit);
    }
}

function initialize() {
    setupThemeToggles(); // Setup theme toggles for both login and main (initial sync)

    // Always attach login form listener
    loginForm.addEventListener('submit', handleLogin);

    if (!checkAuth()) { // If NOT authenticated
        // Show login form
        loginContainer.style.setProperty('display', 'flex', 'important');
        mainContent.style.setProperty('display', 'none', 'important');
        console.log('Not authenticated. Login form displayed. Main app content NOT initialized.');
        return; // IMPORTANT: Stop execution here if not authenticated
    }

    // If authenticated, initialize main content
    console.log('Authenticated. Initializing main app content.');
    initializeMainAppContent();
}

// --- Start Application ---
document.addEventListener('DOMContentLoaded', initialize);
