using System.Net;
using Altob.NtuInvoiceGateway.Models;
using Microsoft.Extensions.Options;

namespace Altob.NtuInvoiceGateway.Middleware;

public class IpWhitelistMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<IpWhitelistMiddleware> _logger;
    private readonly IpWhitelistOptions _ipWhitelistOptions;

    public IpWhitelistMiddleware(
        RequestDelegate next,
        ILogger<IpWhitelistMiddleware> logger,
        IOptions<IpWhitelistOptions> ipWhitelistOptions)
    {
        _next = next;
        _logger = logger;
        _ipWhitelistOptions = ipWhitelistOptions.Value;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 如果 IP 白名單未啟用，直接通過
        if (!_ipWhitelistOptions.Enabled)
        {
            await _next(context);
            return;
        }

        // 只對 Test 開頭的頁面進行 IP 白名單檢查
        var path = context.Request.Path.Value ?? string.Empty;
        if (!path.StartsWith("/Test", StringComparison.OrdinalIgnoreCase))
        {
            await _next(context);
            return;
        }

        var remoteIp = context.Connection.RemoteIpAddress;
        var clientIp = GetClientIp(context);

        _logger.LogDebug("IP Whitelist check for Test page - Path: {Path}, RemoteIp: {RemoteIp}, ClientIp: {ClientIp}",
            path, remoteIp, clientIp);

        // 檢查 RemoteIp 或 ClientIp 是否在白名單中
        var isAllowed = false;

        if (remoteIp != null && IsIpAllowed(remoteIp.ToString()))
        {
            isAllowed = true;
        }
        else if (clientIp != null && IsIpAllowed(clientIp))
        {
            isAllowed = true;
        }

        if (!isAllowed)
        {
            _logger.LogWarning("{ServiceName} - {ActionName} - {CallerIp} - {ClientIp} - IP access denied to Test page: {Path}",
                "NtuInvoiceGateway", "IpWhitelistCheck", remoteIp?.ToString() ?? "Unknown", clientIp, path);

            context.Response.StatusCode = StatusCodes.Status403Forbidden;
            await context.Response.WriteAsync("Access denied. Your IP address is not allowed to access test pages.");
            return;
        }

        await _next(context);
    }

    private bool IsIpAllowed(string ipAddress)
    {
        return _ipWhitelistOptions.AllowedIps.Contains(ipAddress);
    }

    private string? GetClientIp(HttpContext context)
    {
        var forwardedFor = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
        if (!string.IsNullOrEmpty(forwardedFor))
        {
            return forwardedFor.Split(',').FirstOrDefault()?.Trim();
        }
        return null;
    }
}
