using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Ounibo.Catalog.App
{
    /// <summary>
    /// 本机 3D 预览微型服务器 (真实数模用, 完全离线):
    /// 在 127.0.0.1 随机端口服务 新迪查看器本地副本 + 临时 STEP 文件,
    /// 桌面版点【在浏览器中打开 3D 预览】即用系统浏览器打开, 无外部依赖。
    /// </summary>
    public class LocalViewerServer : IDisposable
    {
        readonly TcpListener _listener;
        readonly Thread _thread;
        readonly string _viewerRoot;
        readonly string _stepDir;
        volatile bool _running = true;
        public int Port { get; private set; }

        static readonly Dictionary<string, string> Mime = new Dictionary<string, string>
        {
            { ".html", "text/html; charset=utf-8" }, { ".js", "application/javascript; charset=utf-8" },
            { ".css", "text/css; charset=utf-8" }, { ".png", "image/png" }, { ".jpg", "image/jpeg" },
            { ".wasm", "application/wasm" }, { ".ico", "image/x-icon" }, { ".json", "application/json; charset=utf-8" },
            { ".step", "application/octet-stream" }, { ".stp", "application/octet-stream" }
        };

        public LocalViewerServer(string viewerRoot)
        {
            _viewerRoot = Path.GetFullPath(viewerRoot);
            _stepDir = Path.Combine(Path.GetTempPath(), "onebot_preview");
            Directory.CreateDirectory(_stepDir);
            _listener = new TcpListener(IPAddress.Loopback, 0);
            _listener.Start();
            Port = ((IPEndPoint)_listener.LocalEndpoint).Port;
            _thread = new Thread(Loop) { IsBackground = true, Name = "LocalViewerServer" };
            _thread.Start();
        }

        void Loop()
        {
            while (_running)
            {
                TcpClient client = null;
                try { client = _listener.AcceptTcpClient(); }
                catch { if (!_running) break; Thread.Sleep(500); continue; }
                try { Handle(client); }
                catch { }
                try { client.Close(); } catch { }
            }
        }

        void Handle(TcpClient client)
        {
            var stream = client.GetStream();
            stream.ReadTimeout = 3000;
            stream.WriteTimeout = 15000;
            var reader = new StreamReader(stream, Encoding.ASCII, false, 4096, true);
            var reqLine = reader.ReadLine();
            if (string.IsNullOrEmpty(reqLine)) return;
            var line = reader.ReadLine();
            var guard = 0;
            while (line != null && line != "")
            {
                line = reader.ReadLine();
                if (++guard > 100) break;
            }

            var path = "/";
            var parts = reqLine.Split(' ');
            if (parts.Length >= 2) path = parts[1];
            var qi = path.IndexOf('?');
            if (qi >= 0) path = path.Substring(0, qi);
            if (path == "/") path = "/STEPViewer/index.html";

            // 双根: /STEPViewer/... → 查看器副本; /step/... → 临时 STEP 目录
            string root, rel;
            if (path.StartsWith("/step/", StringComparison.OrdinalIgnoreCase))
            {
                root = _stepDir;
                rel = path.Substring("/step/".Length).Replace('/', '\\');
            }
            else
            {
                root = _viewerRoot;
                rel = path.Substring(1).Replace('/', '\\');
            }

            byte[] bytes; string status = "200 OK"; string ctype = "application/octet-stream";
            var full = Path.GetFullPath(Path.Combine(root, rel));
            if (full.StartsWith(Path.GetFullPath(root), StringComparison.OrdinalIgnoreCase) && File.Exists(full))
            {
                bytes = File.ReadAllBytes(full);
                var ext = Path.GetExtension(full).ToLowerInvariant();
                if (Mime.ContainsKey(ext)) ctype = Mime[ext];
            }
            else
            {
                status = "404 Not Found";
                bytes = Encoding.UTF8.GetBytes("404 Not Found");
                ctype = "text/plain; charset=utf-8";
            }
            var head = Encoding.ASCII.GetBytes(
                "HTTP/1.1 " + status + "\r\nContent-Type: " + ctype +
                "\r\nCache-Control: no-cache\r\nContent-Length: " + bytes.Length +
                "\r\nConnection: close\r\n\r\n");
            stream.Write(head, 0, head.Length);
            stream.Write(bytes, 0, bytes.Length);
            stream.Flush();
        }

        /// <summary>把 STEP 内容写入临时服务目录, 返回浏览器可打开的查看器 URL (嵌入+精简菜单+无模型树)。</summary>
        public string PublishStep(string fileName, byte[] content)
        {
            var safe = Path.GetFileName(fileName.Replace('\\', '/'));
            File.WriteAllBytes(Path.Combine(_stepDir, safe), content);
            return string.Format(
                "http://127.0.0.1:{0}/STEPViewer/index.html?file=/step/{1}&embed=1&bg=grey&menu=min",
                Port, Uri.EscapeDataString(safe));
        }

        public void Dispose()
        {
            _running = false;
            try { _listener.Stop(); } catch { }
        }
    }
}
