namespace ServiceLib.Services.CoreConfig;

public partial class CoreConfigSingboxService
{
    private void GenInbounds()
    {
        try
        {
            var listen = "0.0.0.0";
            var listenPort = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
            var isUsingLocalMixedPort = _node.Address == Global.Loopback && _node.Port == listenPort;
            _coreConfig.inbounds = [];

            if (!context.IsTunEnabled || !isUsingLocalMixedPort)
            {
                var inbound = new Inbound4Sbox()
                {
                    type = nameof(EInboundProtocol.mixed),
                    tag = nameof(EInboundProtocol.socks),
                    listen = Global.Loopback,
                };
                _coreConfig.inbounds.Add(inbound);

                var inboundConf = _config.Inbound.First();
                inbound.listen_port = listenPort;

                if (inboundConf.SecondLocalPortEnabled)
                {
                    var inbound2 = BuildInbound(inbound, EInboundProtocol.socks2, true);
                    _coreConfig.inbounds.Add(inbound2);
                }

                if (inboundConf.AllowLANConn)
                {
                    if (inboundConf.NewPort4LAN)
                    {
                        var inbound3 = BuildInbound(inbound, EInboundProtocol.socks3, true);
                        inbound3.listen = listen;
                        _coreConfig.inbounds.Add(inbound3);

                        //auth
                        if (inboundConf.User.IsNotEmpty() && inboundConf.Pass.IsNotEmpty())
                        {
                            inbound3.users = new() { new() { username = inboundConf.User, password = inboundConf.Pass } };
                        }
                    }
                    else
                    {
                        inbound.listen = listen;
                    }
                }
            }

            if (context.IsTunEnabled)
            {
                if (_config.TunModeItem.Mtu <= 0)
                {
                    _config.TunModeItem.Mtu = Global.TunMtus.First();
                }
                if (_config.TunModeItem.Stack.IsNullOrEmpty())
                {
                    _config.TunModeItem.Stack = Global.TunStacks.First();
                }

                var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(EmbedUtils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
                tunInbound.interface_name = context.IsMacOS ? $"utun{new Random().Next(99)}" : "singbox_tun";
                tunInbound.mtu = _config.TunModeItem.Mtu;
                tunInbound.auto_route = _config.TunModeItem.AutoRoute;
                tunInbound.strict_route = _config.TunModeItem.StrictRoute;
                tunInbound.stack = _config.TunModeItem.Stack;

                var address = _config.TunModeItem.IPv4Address.NullIfEmpty() ?? Global.TunIPv4Address.First();
                tunInbound.address = [address];
                if (_config.TunModeItem.EnableIPv6Address == true)
                {
                    var address6 = _config.TunModeItem.IPv6Address.NullIfEmpty() ?? Global.TunIPv6Address.First();
                    tunInbound.address.Add(address6);
                }
                tunInbound.route_exclude_address = _config.TunModeItem.RouteExcludeAddress;

                _coreConfig.inbounds.Add(tunInbound);
            }
        }
        catch (Exception ex)
        {
            Logging.SaveLog(_tag, ex);
        }
    }

    private Inbound4Sbox BuildInbound(Inbound4Sbox inItem, EInboundProtocol protocol, bool bSocks)
    {
        var inbound = JsonUtils.DeepCopy(inItem);
        inbound.tag = protocol.ToString();
        inbound.listen_port = inItem.listen_port + (int)protocol;
        inbound.type = nameof(EInboundProtocol.mixed);
        return inbound;
    }
}
