using Ayay.SerilogLogs;
using CoreWCF;
using CoreWCF.Configuration;
using CoreWCF.Description;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Player.MJPEG;
using Serilog;
using System.Diagnostics;
using System.Net;

namespace SHH.MjpegPlayer
{
    public static class Bootstrapper
    {
        private static readonly ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core);

        #region LoadConfig

        /// <summary>
        /// 加载配置文件
        /// </summary>
        /// <returns></returns>
        public static MjpegConfig LoadConfig()
        {
            // [修复] 路径处理脆弱性：使用 BaseDirectory 拼接，避免相对路径替换的风险
            // 生产环境：强制使用绝对路径确保能找到配置文件
            if (!Debugger.IsAttached)
            {
                JsonConfigUris.MjpegConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(JsonConfigUris.MjpegConfig));
            }

            // 加载配置文件
            var cfg = JsonConfig.Load<MjpegConfig>(JsonConfigUris.MjpegConfig);
            if (cfg == null)
            {
                cfg = new MjpegConfig();
                JsonConfig.Save(cfg, JsonConfigUris.MjpegConfig, "MjpegServer配置项");
                _sysLog.Warning("未找到配置文件，已生成默认配置: {Path}", JsonConfigUris.MjpegConfig);
            }
            MjpegStatics.Cfg = cfg;
            return cfg;
        }

        #endregion

        #region ValidateEnvironment

        /// <summary>
        /// 检查 IP  与端口
        /// </summary>
        public static void ValidateEnvironment()
        {
            var cfg = MjpegStatics.Cfg;

            // IP 地址检查
            IPAddress? ipAddress;
            if (!IPAddress.TryParse(cfg.SvrMjpegIp, out ipAddress))
            {
                ipAddress = IPAddress.Any;
                _sysLog.Warning("配置的 IP 地址非法，将使用 IPAddress. Any: {Ip}.", cfg.SvrMjpegIp);
            }

            // 端口检查 => Wcf 接收图片接口
            var portsToCheck = new List<int> { cfg.WcfPushImagePort, cfg.SvrMjpegPortBegin, cfg.SvrMjpegPortEnd };
            foreach (var port in portsToCheck)
            {
                if (!port.IsServerPort())
                {
                    _sysLog.Error("端口配置无效, Port: {Port}.", port);
                    ExitApp($"端口配置无效, Port: {port}");
                }
            }

            // 端口检查 => Mjpeg 服务端口
            if (!cfg.SvrMjpegPortBegin.IsServerPort())
            {
                _sysLog.Fatal("WCF 接收端口被占用, Port:{Port}.", cfg.WcfPushImagePort);
                // 退出应用
                ExitApp("端口占用.");
            }

            // [修复] 循环逻辑错误：将 < 改为 <=，确保最后一个端口也被检测
            for (var i = cfg.SvrMjpegPortBegin; i <= cfg.SvrMjpegPortEnd; i++)
            {
                if (!i.PortOccupiedProc())
                {
                    // 退出应用
                    _sysLog.Fatal("MJPEG 监听端口被占用, Port:{Port}", i);
                    ExitApp($"MJPEG 监听端口被占用, Port:{i}");
                }
            }
        }

        #endregion

        #region StartWcfEngine

        /// <summary>
        /// 内部 WCF 引擎初始化 (CoreWCF)
        /// </summary>
        public static void StartWcfEngine(MjpegConfig cfg)
        {
            // Optimized: 内存监控提升
            MemoryWatchdog.Start(300, 2048);

            var builder = WebApplication.CreateBuilder();
            builder.WebHost.UseUrls($"http://*:{cfg.WcfPushImagePort}");

            // 托管日志
            builder.Host.UseSerilog(_sysLog);

            builder.Services.AddServiceModelServices();
            builder.Services.AddServiceModelMetadata();
            builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>()
                            .AddSingleton<MjpegImagesService>();

            var app = builder.Build();

            var wsBinding = new WSHttpBinding(SecurityMode.None);
            wsBinding.MaxReceivedMessageSize = cfg.SvrPushImageMaxRecMsgSize;

            // Modified: [原因] 强制转换 IApplicationBuilder 修复 UseServiceModel 的二义性
            ((IApplicationBuilder)app).UseServiceModel(serviceBuilder =>
            {
                serviceBuilder.AddService<MjpegImagesService>(opt =>
                {
                    opt.BaseAddresses.Add(new Uri($"http://0.0.0.0:{cfg.WcfPushImagePort}"));
                })
                .AddServiceEndpoint<MjpegImagesService, IMjpegImagesService>(
                    wsBinding,
                    $"/{cfg.SvrNamePushImage}",
                    new Uri($"http://0.0.0.0:{cfg.WcfPushImagePort}/{cfg.SvrNamePushImage}")
                );
            });

            // 关闭元数据暴露增强安全性
            var meta = app.Services.GetRequiredService<ServiceMetadataBehavior>();
            meta.HttpGetEnabled = false;
            meta.HttpsGetEnabled = false;

            Task.Run(() => app.Run());
        }

        #endregion

        #region ExitApp

        /// <summary>
        /// 应用程序退出
        /// </summary>
        /// <param name="exitMsg"></param>
        /// <param name="waitSeconds"></param>
        public static void ExitApp(string exitMsg, int waitSeconds = 5)
        {
            // [修复] 尝试停止所有 MjpegServer 监听
            try { MjpegServer.StopAll(); } catch { }

            var iSleep = waitSeconds * 2;
            for (var i = 0; i < iSleep; i++)
            {
                Thread.Sleep(500);
            }

            // 退出程序
            Environment.Exit(0);
        }

        #endregion
    }
}