using System;
using System.Linq;
using PolyTrader.Modules.CopyTrading.Persistence.Ef;
using PolyTrader.Tests.TestSupport;
using PolyTraderSharp.Models;
using Xunit;

namespace PolyTrader.Tests
{
    public class RepositoryEdgeCaseTests
    {
        private static EfTrackedTraderRepository TraderRepo() =>
            new(new InMemoryContextFactory<CopyTradingDbContext>(o => new CopyTradingDbContext(o)));

        private static EfMasterTraderHistoryRepository HistoryRepo() =>
            new(new InMemoryContextFactory<CopyTradingDbContext>(o => new CopyTradingDbContext(o)));

        [Fact]
        public void GetAll_on_empty_repo_returns_empty_not_null()
        {
            var repo = TraderRepo();
            var all = repo.GetAll();
            Assert.NotNull(all);
            Assert.Empty(all);
        }

        [Fact]
        public void Update_alias_behaves_like_upsert_for_existing()
        {
            var repo = TraderRepo();
            repo.Upsert(new TrackedTrader { Id = 1, DisplayName = "A" });
            repo.Update(new TrackedTrader { Id = 1, DisplayName = "B" });

            Assert.Equal("B", Assert.Single(repo.GetAll()).DisplayName);
        }

        [Fact]
        public void Two_factories_are_isolated_from_each_other()
        {
            var a = TraderRepo();
            var b = TraderRepo();
            a.Upsert(new TrackedTrader { Id = 1 });

            Assert.Single(a.GetAll());
            Assert.Empty(b.GetAll());
        }

        [Fact]
        public void History_Exists_is_inclusive_on_window_boundaries()
        {
            var repo = HistoryRepo();
            var t = new DateTime(2026, 7, 1, 12, 0, 0, DateTimeKind.Utc);
            repo.Insert(new MasterTraderHistoryRecord { TraderId = 1, TokenId = "tok", ClosedAt = t });

            // Fenster endet exakt auf dem Zeitpunkt (untere Grenze)
            Assert.True(repo.Exists(1, "tok", t, t.AddSeconds(2)));
            // Fenster beginnt exakt auf dem Zeitpunkt (obere Grenze)
            Assert.True(repo.Exists(1, "tok", t.AddSeconds(-2), t));
        }

        [Fact]
        public void GetByTraderSince_is_inclusive_on_cutoff()
        {
            var repo = HistoryRepo();
            var cutoff = new DateTime(2026, 7, 1, 0, 0, 0, DateTimeKind.Utc);
            repo.Insert(new MasterTraderHistoryRecord { TraderId = 1, ClosedAt = cutoff });          // genau am Cutoff -> drin
            repo.Insert(new MasterTraderHistoryRecord { TraderId = 1, ClosedAt = cutoff.AddTicks(-1) }); // knapp davor -> raus

            Assert.Single(repo.GetByTraderSince(1, cutoff));
        }
    }
}
