using Lucene.Net.Attributes;
using Lucene.Net.Util;
using NUnit.Framework;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
#nullable enable

namespace Lucene.Net.Replicator.Http
{
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    /// <summary>
    /// Unit tests for the async methods on <see cref="HttpClientBase"/> that
    /// use a mocked <see cref="HttpMessageHandler"/>, so we can assert properties
    /// of the HTTP interaction (streaming behavior, response lifetime, cancellation)
    /// that are difficult to verify via the full integration tests.
    /// </summary>
    [LuceneNetSpecific]
    public class HttpClientBaseTest : LuceneTestCase
    {
        private sealed class TestableHttpClientBase : HttpClientBase
        {
            public TestableHttpClientBase(string url, HttpClient client)
                : base(url, client)
            {
            }

            public new Task<HttpResponseMessage> ExecuteGetAsync(string request, string[]? parameters, CancellationToken cancellationToken)
                => base.ExecuteGetAsync(request, parameters, cancellationToken);

            public new Task<HttpResponseMessage> ExecutePostAsync(string request, HttpContent content, CancellationToken cancellationToken, params string[]? parameters)
                => base.ExecutePostAsync(request, content, cancellationToken, parameters);
        }

        private sealed class MockHttpMessageHandler : HttpMessageHandler
        {
            // ReSharper disable once PropertyCanBeMadeInitOnly.Local - not trivially supported on .NET Framework
            public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> Handler { get; set; } =
                (_, _) => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("ok") });

            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                return Handler(request, cancellationToken);
            }
        }

        /// <summary>
        /// A stream that blocks on read until the test releases it, so we can
        /// prove the caller receives the response message before the body has
        /// been consumed (i.e. the client is using ResponseHeadersRead, not
        /// the default ResponseContentRead which buffers the entire body).
        /// </summary>
        private sealed class BlockingStream : Stream
        {
            private readonly ManualResetEventSlim gate;

            public BlockingStream(ManualResetEventSlim gate)
            {
                this.gate = gate;
            }

            public override bool CanRead => true;
            public override bool CanSeek => false;
            public override bool CanWrite => false;
            public override long Length => throw new NotSupportedException();
            public override long Position { get => 0; set => throw new NotSupportedException(); }

            public override void Flush() { }
            public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
            public override void SetLength(long value) => throw new NotSupportedException();
            public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();

            public override int Read(byte[] buffer, int offset, int count)
            {
                gate.Wait();
                return 0;
            }
        }

        [Test]
        public async Task ExecuteGetAsync_ServerReturns500_ThrowsBeforeReturning()
        {
            var handler = new MockHttpMessageHandler
            {
                Handler = (_, _) => Task.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    ReasonPhrase = "boom",
                    Content = new StringContent("server failed"),
                }),
            };
            using var client = new TestableHttpClientBase("http://example/", new HttpClient(handler));

            try
            {
                using var response = await client.ExecuteGetAsync("action", parameters: null, CancellationToken.None);
                fail("expected exception");
            }
            catch (Exception e) when (e.IsThrowable())
            {
                // expected
            }
        }

        [Test]
        public async Task ExecuteGetAsync_LargeBody_ReturnsBeforeBodyConsumed()
        {
            // Give the handler a response whose body would block forever if the
            // client tried to buffer it. The async GET should return immediately
            // after the headers arrive (HttpCompletionOption.ResponseHeadersRead).
            using var gate = new ManualResetEventSlim(false);
            var handler = new MockHttpMessageHandler
            {
                Handler = (_, _) =>
                {
                    // ReSharper disable once AccessToDisposedClosure
                    var content = new StreamContent(new BlockingStream(gate));
                    var resp = new HttpResponseMessage(HttpStatusCode.OK) { Content = content };
                    return Task.FromResult(resp);
                },
            };
            using var client = new TestableHttpClientBase("http://example/", new HttpClient(handler));

            var task = client.ExecuteGetAsync("action", parameters: null, CancellationToken.None);
            var winner = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(2)));
            try
            {
                assertSame("ExecuteGetAsync should return before the response body is consumed", task, winner);
                using var response = await task;
                assertTrue(response.IsSuccessStatusCode);
            }
            finally
            {
                gate.Set();
            }
        }

        [Test]
        public async Task ExecuteGetAsync_CancellationToken_IsPropagated()
        {
            using var cts = new CancellationTokenSource();
            var handler = new MockHttpMessageHandler
            {
                Handler = async (_, ct) =>
                {
                    await Task.Delay(TimeSpan.FromSeconds(10), ct).ConfigureAwait(false);
                    return new HttpResponseMessage(HttpStatusCode.OK);
                },
            };
            using var client = new TestableHttpClientBase("http://example/", new HttpClient(handler));

            var task = client.ExecuteGetAsync("action", parameters: null, cts.Token);
            // ReSharper disable once MethodHasAsyncOverload - not supported on .NET Framework
            cts.Cancel();

            try
            {
                using var response = await task;
                fail("expected cancellation");
            }
            catch (OperationCanceledException)
            {
                // expected
            }
        }

        [Test]
        public async Task ExecutePostAsync_ServerReturns500_ThrowsBeforeReturning()
        {
            var handler = new MockHttpMessageHandler
            {
                Handler = (_, _) => Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadGateway)
                {
                    ReasonPhrase = "bad gateway",
                    Content = new StringContent(string.Empty),
                }),
            };
            using var client = new TestableHttpClientBase("http://example/", new HttpClient(handler));

            try
            {
                using var response = await client.ExecutePostAsync(
                    "action",
                    new StringContent("body", Encoding.UTF8),
                    CancellationToken.None);
                fail("expected exception");
            }
            catch (Exception e) when (e.IsThrowable())
            {
                // expected
            }
        }

        /// <summary>
        /// HttpResponseMessage subclass that counts Dispose calls, so we can
        /// verify response lifetime invariants without a real server.
        /// </summary>
        private sealed class DisposeTrackingResponse : HttpResponseMessage
        {
            private int disposeCount;
            public int DisposeCount => disposeCount;

            public DisposeTrackingResponse(HttpStatusCode status) : base(status) { }

            protected override void Dispose(bool disposing)
            {
                Interlocked.Increment(ref disposeCount);
                base.Dispose(disposing);
            }
        }

        [Test]
        public async Task ObtainFileAsync_WhenBodyReadFails_DisposesResponse()
        {
            // Regression test for response-leak bug: ObtainFileAsync hands response
            // ownership to the returned stream only on success; on failure the
            // response must be disposed of.
            DisposeTrackingResponse? capturedResponse = null;
            var handler = new MockHttpMessageHandler
            {
                Handler = (_, _) =>
                {
                    capturedResponse = new DisposeTrackingResponse(HttpStatusCode.OK)
                    {
                        Content = new ThrowingContent(),
                    };
                    return Task.FromResult<HttpResponseMessage>(capturedResponse);
                },
            };
            using var replicator = new HttpReplicator("http://example/", new HttpClient(handler));

            try
            {
                // ReSharper disable once UseAwaitUsing - not supported on .NET Framework
                using var stream = await replicator.ObtainFileAsync("s", "src", "file.dat");
                fail("expected exception");
            }
            catch (Exception e) when (e.IsThrowable())
            {
                // expected
            }

            assertNotNull(capturedResponse);
            assertTrue("response must be disposed when obtaining the file fails", capturedResponse!.DisposeCount > 0);
        }

        /// <summary>
        /// <see cref="HttpContent"/> whose stream creation throws — used to simulate the
        /// post-headers failure path in ObtainFileAsync.
        /// </summary>
        private sealed class ThrowingContent : HttpContent
        {
            protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context)
                => throw new IOException("simulated body failure");

            protected override bool TryComputeLength(out long length)
            {
                length = 0;
                return false;
            }

#if FEATURE_HTTPCONTENT_READASSTREAM
            protected override Stream CreateContentReadStream(CancellationToken cancellationToken)
                => throw new IOException("simulated body failure");
#endif

            protected override Task<Stream> CreateContentReadStreamAsync()
                => Task.FromException<Stream>(new IOException("simulated body failure"));
        }

        [Test]
        public void PublishAsync_ReturnsFaultedTask_DoesNotThrowSynchronously()
        {
            // The method must return a Task that completes with the exception,
            // not throw synchronously — otherwise callers using Task.WhenAll or
            // fire-and-forget patterns would see the exception in the wrong place.
            using var replicator = new HttpReplicator("http://example/", new HttpClient(new MockHttpMessageHandler()));

            Task publishTask = replicator.PublishAsync(revision: null!);

            assertNotNull(publishTask);
            assertTrue("PublishAsync should return a faulted Task", publishTask.IsFaulted);
            assertNotNull(publishTask.Exception);
        }

        [Test]
        public async Task ExecutePostAsync_CancellationToken_IsPropagated()
        {
            using var cts = new CancellationTokenSource();
            var handler = new MockHttpMessageHandler
            {
                Handler = async (_, ct) =>
                {
                    await Task.Delay(TimeSpan.FromSeconds(10), ct).ConfigureAwait(false);
                    return new HttpResponseMessage(HttpStatusCode.OK);
                },
            };
            using var client = new TestableHttpClientBase("http://example/", new HttpClient(handler));

            var task = client.ExecutePostAsync("action", new StringContent("x"), cts.Token);
            // ReSharper disable once MethodHasAsyncOverload - not supported on .NET Framework
            cts.Cancel();

            try
            {
                using var response = await task;
                fail("expected cancellation");
            }
            catch (OperationCanceledException)
            {
                // expected
            }
        }
    }
}
