using System;
using System.IO;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;

namespace MRCC.Launcher;

public partial class MainWindow : Window
{
    private WebView2? _wv;

    public MainWindow()
    {
        InitializeComponent();
    }

    private async void OnWindowLoaded(object sender, RoutedEventArgs e)
    {
        try
        {
            var gameDir = FindGamePath();
            if (gameDir == null)
            {
                Content = new TextBlock { Text = "游戏文件未找到", Foreground = System.Windows.Media.Brushes.White, FontSize = 14, Margin = new Thickness(20) };
                return;
            }

            var port = GameServer.Start(gameDir);
            var url = $"http://localhost:{port}/voxel-world.html";

            _wv = new WebView2();
            Content = _wv;

            await _wv.EnsureCoreWebView2Async();
            _wv.CoreWebView2.Settings.IsWebMessageEnabled = true;
            _wv.CoreWebView2.WebMessageReceived += OnWebMessage;

            _wv.CoreWebView2.Navigate(url);
            Program.Log($"Launcher UI loaded: {url}");
        }
        catch (Exception ex)
        {
            Program.Log($"Launcher load failed: {ex}");
        }
    }

    private void OnWebMessage(object? sender, CoreWebView2WebMessageReceivedEventArgs e)
    {
        try
        {
            // WebView2 的 postMessage 会 JSON 编码，需先解一层
            var rawJson = e.TryGetWebMessageAsString();
            if (string.IsNullOrEmpty(rawJson)) return;
            using var doc = JsonDocument.Parse(rawJson);
            var root = doc.RootElement;
            if (!root.TryGetProperty("action", out var action) || action.GetString() != "launch_game") return;

            var username = "Player";
            if (root.TryGetProperty("username", out var u) && u.ValueKind == JsonValueKind.String)
                username = u.GetString()!;
            // 不再启动 Luanti —— HTML5 世界直接在 WebView2 内运行
            Program.Log($"Game launch requested by: {username}");
        }
        catch (Exception ex) { Program.Log($"WebMessage error: {ex}"); }
    }

    public static string? FindGamePath()
    {
        var exeDir = AppContext.BaseDirectory;
        foreach (var p in new[] { "game", "../game", "../../../prototype", "../../prototype", "../prototype" })
        {
            var full = Path.GetFullPath(Path.Combine(exeDir, p));
            if (Directory.Exists(full) && File.Exists(Path.Combine(full, "voxel-world.html")))
                return full;
        }
        return null;
    }
}

// HTTP server for static files
public static class GameServer
{
    private static HttpListener? _listener;
    private static CancellationTokenSource? _cts;
    private static string _gameDir = "";

    public static int Start(string gameDir)
    {
        _gameDir = gameDir;
        var port = FindFreePort();
        _cts = new CancellationTokenSource();
        _listener = new HttpListener();
        _listener.Prefixes.Add($"http://localhost:{port}/");
        _listener.Start();
        Task.Run(() => ListenLoop(_cts.Token));
        return port;
    }

    public static void Stop()
    {
        _cts?.Cancel();
        try { _listener?.Stop(); } catch { }
        try { _listener?.Close(); } catch { }
    }

    private static async Task ListenLoop(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            try { var ctx = await _listener!.GetContextAsync().WaitAsync(ct); _ = Task.Run(() => Handle(ctx)); }
            catch (OperationCanceledException) { break; }
            catch (HttpListenerException) { break; }
        }
    }

    private static async Task Handle(HttpListenerContext ctx)
    {
        try
        {
            var path = ctx.Request.Url!.AbsolutePath.TrimStart('/');
            if (string.IsNullOrEmpty(path)) path = "voxel-world.html";
            var fp = Path.GetFullPath(Path.Combine(_gameDir, path));
            if (!fp.StartsWith(_gameDir, StringComparison.OrdinalIgnoreCase) || !File.Exists(fp))
            { ctx.Response.StatusCode = 404; ctx.Response.Close(); return; }

            var ct = Path.GetExtension(fp).ToLowerInvariant() switch
            {
                ".html" => "text/html; charset=utf-8", ".css" => "text/css",
                ".js" => "application/javascript", ".json" => "application/json",
                ".png" => "image/png", ".jpg" or ".jpeg" => "image/jpeg",
                ".svg" => "image/svg+xml", _ => "application/octet-stream"
            };
            var bytes = await File.ReadAllBytesAsync(fp);
            ctx.Response.ContentType = ct;
            ctx.Response.ContentLength64 = bytes.Length;
            ctx.Response.Headers.Add("Access-Control-Allow-Origin", "*");
            ctx.Response.Headers.Add("Cache-Control", "no-cache");
            await ctx.Response.OutputStream.WriteAsync(bytes);
            ctx.Response.Close();
        }
        catch { try { ctx.Response.StatusCode = 500; ctx.Response.Close(); } catch { } }
    }

    private static int FindFreePort()
    {
        var l = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Loopback, 0);
        l.Start(); var port = ((System.Net.IPEndPoint)l.LocalEndpoint).Port; l.Stop();
        return port;
    }
}
