use std::fs;
use std::path::PathBuf;
use std::net::TcpListener;
use std::io::{Read, Write};
use std::thread;
use std::time::Duration;
use std::sync::{Arc, Mutex};

use crate::parser::parse_liquid;
use crate::optimizer::optimize_ast;
use crate::generator::js::generate_js;

/// Starts a local development server for live preview and hot reload.
/// 
/// # Arguments
/// * `input_file` - The path to the main `.liq` file to watch and compile.
pub fn start_dev_server(input_file: PathBuf) {
    let port = 3000;
    let listener = TcpListener::bind(format!("127.0.0.1:{}", port)).unwrap_or_else(|err| {
        eprintln!("Failed to bind to port {}: {}", port, err);
        std::process::exit(1);
    });

    println!("====================================================");
    println!("   🔥 LIQUID LIVE DEVELOPMENT SERVER STARTED 🔥");
    println!("   Local Address: http://127.0.0.1:{}", port);
    println!("   Watching file: {}", input_file.display());
    println!("   Press Ctrl+C to stop the development server");
    println!("====================================================");

    // Initial compile on startup
    let initial_js = match fs::read_to_string(&input_file) {
        Ok(src) => match parse_liquid(&src) {
            Ok(ast) => {
                let opt = optimize_ast(ast);
                let cls = opt.classes.first().map(|c| c.name.clone()).unwrap_or_else(|| "Counter".to_string());
                let js = generate_js(&opt);
                Some((js, cls))
            }
            Err(err) => {
                eprintln!("[Dev Server] Initial compilation failed: {}", err);
                None
            }
        },
        Err(err) => {
            eprintln!("[Dev Server] Failed to read initial file: {}", err);
            None
        }
    };

    let (init_js, init_cls) = initial_js.unwrap_or_else(|| (String::new(), "Counter".to_string()));

    // Shared state for compiled JS code, main class name, and version counter
    let compiled_js = Arc::new(Mutex::new(init_js));
    let class_name = Arc::new(Mutex::new(init_cls));
    let version = Arc::new(Mutex::new(1));

    let compiled_js_clone = Arc::clone(&compiled_js);
    let class_name_clone = Arc::clone(&class_name);
    let version_clone = Arc::clone(&version);
    let input_clone = input_file.clone();

    // Spawn a background thread to watch for file changes
    thread::spawn(move || {
        let mut last_modified = fs::metadata(&input_clone)
            .and_then(|meta| meta.modified())
            .ok();

        loop {
            if let Ok(meta) = fs::metadata(&input_clone) {
                if let Ok(modified) = meta.modified() {
                    if Some(modified) != last_modified {
                        last_modified = Some(modified);
                        // Re-compile file
                        if let Ok(src) = fs::read_to_string(&input_clone) {
                            if let Ok(ast) = parse_liquid(&src) {
                                let opt = optimize_ast(ast);
                                let js_code = generate_js(&opt);
                                let detected_class = opt.classes.first().map(|c| c.name.clone()).unwrap_or_else(|| "Counter".to_string());
                                
                                {
                                    let mut lock_js = compiled_js_clone.lock().unwrap();
                                    *lock_js = js_code;
                                }
                                {
                                    let mut lock_cls = class_name_clone.lock().unwrap();
                                    *lock_cls = detected_class;
                                }
                                
                                let mut lock_ver = version_clone.lock().unwrap();
                                *lock_ver += 1;
                                
                                println!("[Hot Reload] File changed. Compiled successfully. Version: {}", *lock_ver);
                            } else {
                                eprintln!("[Hot Reload] Error parsing changes. Fix syntax error to reload.");
                            }
                        }
                    }
                }
            }
            thread::sleep(Duration::from_millis(150));
        }
    });

    // Accept connections
    for stream in listener.incoming() {
        if let Ok(mut stream) = stream {
            let compiled_js_c = Arc::clone(&compiled_js);
            let class_name_c = Arc::clone(&class_name);
            let version_c = Arc::clone(&version);
            let filename_display = input_file.file_name().unwrap_or_default().to_string_lossy().into_owned();
            
            thread::spawn(move || {
                let mut buffer = [0; 1024];
                if stream.read(&mut buffer).is_ok() {
                    let request = String::from_utf8_lossy(&buffer);
                    let mut parts = request.split_whitespace();
                    let method = parts.next().unwrap_or("");
                    let path = parts.next().unwrap_or("");

                    if method == "GET" {
                        if path == "/" {
                            let html = serve_dashboard(&filename_display);
                            let response = format!(
                                "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                                html.len(),
                                html
                            );
                            let _ = stream.write_all(response.as_bytes());
                        } else if path == "/app" {
                            let cls = class_name_c.lock().unwrap().clone();
                            let html = serve_app_shell(&cls);
                            let response = format!(
                                "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                                html.len(),
                                html
                            );
                            let _ = stream.write_all(response.as_bytes());
                        } else if path == "/app.js" {
                            let js = compiled_js_c.lock().unwrap().clone();
                            let response = format!(
                                "HTTP/1.1 200 OK\r\nContent-Type: application/javascript\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                                js.len(),
                                js
                            );
                            let _ = stream.write_all(response.as_bytes());
                        } else if path == "/version" {
                            let ver = version_c.lock().unwrap().to_string();
                            let response = format!(
                                "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
                                ver.len(),
                                ver
                            );
                            let _ = stream.write_all(response.as_bytes());
                        } else {
                            let response = "HTTP/1.1 404 NOT FOUND\r\nContent-Length: 0\r\nConnection: close\r\n\r\n";
                            let _ = stream.write_all(response.as_bytes());
                        }
                    }
                }
            });
        }
    }
}

fn serve_dashboard(filename: &str) -> String {
    let raw_html = r#"<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Liquid Live Preview Dashboard</title>
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: 'Plus Jakarta Sans', sans-serif;
            background-color: #0b0f19;
            color: #f3f4f6;
            display: flex;
            height: 100vh;
            overflow: hidden;
        }
        
        /* Sidebar */
        .sidebar {
            width: 320px;
            background: rgba(17, 24, 39, 0.95);
            border-right: 1px solid rgba(255, 255, 255, 0.08);
            display: flex;
            flex-direction: column;
            padding: 30px 24px;
            backdrop-filter: blur(12px);
        }
        .logo {
            font-size: 24px;
            font-weight: 700;
            background: linear-gradient(135deg, #a5b4fc, #6366f1);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            margin-bottom: 40px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .logo-dot {
            width: 10px;
            height: 10px;
            background-color: #6366f1;
            border-radius: 50%;
            box-shadow: 0 0 12px #6366f1;
        }
        .section-title {
            font-size: 12px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.1em;
            color: #6b7280;
            margin-bottom: 16px;
        }
        .device-btn {
            background: transparent;
            border: 1px solid rgba(255, 255, 255, 0.05);
            color: #9ca3af;
            padding: 14px 18px;
            border-radius: 12px;
            cursor: pointer;
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 14px;
            font-weight: 500;
            margin-bottom: 12px;
            transition: all 0.2s ease;
            text-align: left;
            width: 100%;
        }
        .device-btn:hover {
            background: rgba(255, 255, 255, 0.03);
            color: #f3f4f6;
            border-color: rgba(255, 255, 255, 0.15);
        }
        .device-btn.active {
            background: linear-gradient(135deg, rgba(99, 102, 241, 0.15), rgba(99, 102, 241, 0.05));
            border-color: #6366f1;
            color: #a5b4fc;
        }
        .status-container {
            margin-top: auto;
            background: rgba(255, 255, 255, 0.03);
            border: 1px solid rgba(255, 255, 255, 0.05);
            padding: 16px;
            border-radius: 12px;
        }
        .status-header {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 14px;
            font-weight: 600;
            margin-bottom: 8px;
        }
        .status-indicator {
            width: 8px;
            height: 8px;
            background-color: #10b981;
            border-radius: 50%;
            box-shadow: 0 0 10px #10b981;
            animation: pulse 2s infinite;
        }
        @keyframes pulse {
            0% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
            70% { transform: scale(1); box-shadow: 0 0 0 6px rgba(16, 185, 129, 0); }
            100% { transform: scale(0.95); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
        }
        .status-desc {
            font-size: 12px;
            color: #9ca3af;
            line-height: 1.5;
        }
        
        /* Main Viewport Workspace */
        .workspace {
            flex-grow: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            background: radial-gradient(circle at center, #111827 0%, #030712 100%);
            position: relative;
        }
        
        /* Device Emulator Frames */
        .emulator-container {
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
            position: relative;
        }
        
        /* iOS / Android Phone Frame style */
        .emulator-container.phone {
            width: 375px;
            height: 812px;
            border: 12px solid #1e293b;
            border-radius: 40px;
            background: #121212;
            overflow: hidden;
        }
        
        /* Desktop Frame style */
        .emulator-container.desktop {
            width: 1024px;
            height: 640px;
            border: 8px solid #334155;
            border-radius: 16px;
            background: #121212;
            overflow: hidden;
        }
        
        /* Web Frame style (fullscreen workspace) */
        .emulator-container.web {
            width: 100%;
            height: 100%;
            border: none;
            border-radius: 0;
        }
        
        iframe {
            width: 100%;
            height: 100%;
            border: none;
            background: transparent;
        }
        
        /* Notch representation for phone style */
        .phone::before {
            content: "";
            position: absolute;
            top: 0;
            left: 50%;
            transform: translateX(-50%);
            width: 150px;
            height: 24px;
            background: #1e293b;
            border-bottom-left-radius: 18px;
            border-bottom-right-radius: 18px;
            z-index: 10;
        }
    </style>
</head>
<body>
    <!-- Sidebar Controls -->
    <div class="sidebar">
        <div class="logo">
            <div class="logo-dot"></div>
            <span>Liquid Live</span>
        </div>
        
        <div class="section-title">Emulator Frame</div>
        <button class="device-btn active" onclick="setDevice('phone', this)">
            📱 Mobile View (iOS / Android)
        </button>
        <button class="device-btn" onclick="setDevice('desktop', this)">
            💻 Desktop Frame (Windows)
        </button>
        <button class="device-btn" onclick="setDevice('web', this)">
            🌐 Web Viewport (WASM)
        </button>
        
        <div class="status-container">
            <div class="status-header">
                <div class="status-indicator"></div>
                <span>DevServer Connected</span>
            </div>
            <div class="status-desc">
                Hot Reload and Hot Restart active. Changes in <b>__FILENAME__</b> will update instantly.
            </div>
        </div>
    </div>
    
    <!-- Emulator Viewport -->
    <div class="workspace">
        <div id="emulator" class="emulator-container phone">
            <iframe id="app-frame" src="/app"></iframe>
        </div>
    </div>

    <script>
        function setDevice(type, btn) {
            // Remove active classes
            document.querySelectorAll('.device-btn').forEach(b => b.classList.remove('active'));
            btn.classList.add('active');
            
            const emulator = document.getElementById('emulator');
            emulator.className = 'emulator-container ' + type;
        }
    </script>
</body>
</html>
"#;
    raw_html.replace("__FILENAME__", filename)
}

fn serve_app_shell(class_name: &str) -> String {
    let raw_html = r#"<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Liquid App Preview</title>
    <style>
        body {
            margin: 0;
            padding: 40px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: #121212;
            color: #ffffff;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        button {
            padding: 12px 24px;
            font-size: 16px;
            font-weight: 600;
            background: linear-gradient(135deg, #6366f1, #4f46e5);
            color: white;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            transition: transform 0.1s ease, filter 0.2s ease;
        }
        button:hover {
            filter: brightness(1.1);
        }
        button:active {
            transform: scale(0.98);
        }
    </style>
</head>
<body>
    <div id="app"></div>
    
    <!-- Load compiled app class -->
    <script src="/app.js"></script>
    
    <script>
        let appInstance = null;
        
        function saveState() {
            const state = {};
            if (appInstance) {
                const instanceState = {};
                for (const k in appInstance) {
                    if (appInstance.hasOwnProperty(k) && typeof appInstance[k] !== 'function' && k !== 'listeners') {
                        instanceState[k] = appInstance[k];
                    }
                }
                state.__appInstance = instanceState;
            }
            for (const key in window) {
                if (key.endsWith("Store") && window[key] && typeof window[key] === 'object') {
                    const storeState = {};
                    for (const prop in window[key]) {
                        if (window[key].hasOwnProperty(prop) && typeof window[key][prop] !== 'function' && prop !== 'listeners') {
                            storeState[prop] = window[key][prop];
                        }
                    }
                    state[key] = storeState;
                }
            }
            sessionStorage.setItem("liquid_state_preservation", JSON.stringify(state));
        }

        function restoreState() {
            const saved = sessionStorage.getItem("liquid_state_preservation");
            if (!saved) return;
            sessionStorage.removeItem("liquid_state_preservation");
            try {
                const state = JSON.parse(saved);
                if (state.__appInstance && appInstance) {
                    for (const k in state.__appInstance) {
                        appInstance[k] = state.__appInstance[k];
                    }
                    if (typeof appInstance.update_dom === 'function') {
                        appInstance.update_dom();
                    }
                }
                for (const key in state) {
                    if (key !== "__appInstance" && window[key]) {
                        for (const prop in state[key]) {
                            window[key][prop] = state[key][prop];
                        }
                        if (typeof window[key].notify === 'function') {
                            window[key].notify();
                        }
                    }
                }
            } catch (e) {
                console.error("[Hot Reload] Failed to restore state:", e);
            }
        }

        function renderApp() {
            if (typeof Counter !== 'undefined') {
                appInstance = new Counter();
                appInstance.render("app");
                restoreState();
            } else {
                document.getElementById("app").innerHTML = "Loading component...";
            }
        }
        
        renderApp();

        // Hot Reload / Hot Restart watcher polling
        let currentVersion = -1;
        setInterval(async () => {
            try {
                const res = await fetch("/version");
                const ver = parseInt(await res.text(), 10);
                if (currentVersion === -1) {
                    currentVersion = ver;
                } else if (ver !== currentVersion) {
                    currentVersion = ver;
                    console.log("[Hot Reload] Saving state & reloading...");
                    saveState();
                    location.reload();
                }
            } catch (err) {
                // Ignore connection errors during server restarts
            }
        }, 300);
    </script>
</body>
</html>
"#;
    // Replace "Counter" dynamically with the compiled component class name
    raw_html.replace("Counter", class_name)
}
