// Services/IpFilialeService.cs
using System.Net;
using Microsoft.Data.SqlClient;
using System.Data;

namespace WerksverkaufScanner.Services;

public class IpFilialeService
{
    private readonly string _cs;
    public IpFilialeService(IConfiguration cfg)
        => _cs = cfg.GetConnectionString("Default")
               ?? throw new InvalidOperationException("ConnectionStrings:Default fehlt.");

    public async Task<int?> TryMatchFilialeAsync(IPAddress clientIp)
    {
        if (clientIp == null) return null;

        await using var con = new SqlConnection(_cs);
        await con.OpenAsync();

        const string sql = @"
            SELECT FilialId, IpStart, IpEnd
            FROM [KassensystemTest].[KS].[FilialIpRange] WITH (NOLOCK);";

        var ranges = new List<(int FilialId, IPAddress Start, IPAddress End)>();

        await using (var cmd = new SqlCommand(sql, con))
        await using (var r = await cmd.ExecuteReaderAsync())
        {
            while (await r.ReadAsync())
            {
                var fid = r.GetInt32(0);
                if (IPAddress.TryParse(r.GetString(1), out var start) &&
                    IPAddress.TryParse(r.GetString(2), out var end))
                {
                    ranges.Add((fid, start, end));
                }
            }
        }

        foreach (var rg in ranges)
        {
            if (IsInRange(clientIp, rg.Start, rg.End))
                return rg.FilialId;
        }

        return null;
    }

    private static bool IsInRange(IPAddress ip, IPAddress start, IPAddress end)
    {
        // nur IPv4: in Bytes vergleichen
        var ipBytes = ip.GetAddressBytes();
        var startBytes = start.GetAddressBytes();
        var endBytes = end.GetAddressBytes();

        if (ipBytes.Length != startBytes.Length || ipBytes.Length != endBytes.Length)
            return false; // IPv4/IPv6 mismatch

        bool gteStart = true, lteEnd = true;
        for (int i = 0; i < ipBytes.Length; i++)
        {
            if (ipBytes[i] < startBytes[i]) { gteStart = false; break; }
            if (ipBytes[i] > startBytes[i]) { break; }
        }
        for (int i = 0; i < ipBytes.Length; i++)
        {
            if (ipBytes[i] > endBytes[i]) { lteEnd = false; break; }
            if (ipBytes[i] < endBytes[i]) { break; }
        }
        return gteStart && lteEnd;
    }
}
