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

namespace PolyTrader.Tests
{
    public class PositionRepositoryTests
    {
        private static EfPositionRepository NewRepo() =>
            new(new InMemoryContextFactory<CoreDbContext>(o => new CoreDbContext(o)));

        [Fact]
        public void Live_and_demo_positions_are_kept_separate_per_account()
        {
            var repo = NewRepo();
            repo.UpsertLive(1, new Position { TokenId = "t1" });
            repo.UpsertDemo(1, new Position { TokenId = "t1" });
            repo.UpsertLive(2, new Position { TokenId = "t1" });

            Assert.Single(repo.GetLive(1));
            Assert.Single(repo.GetDemo(1));
            Assert.Single(repo.GetLive(2));
            Assert.Empty(repo.GetDemo(2));
        }

        [Fact]
        public void Upsert_sets_account_and_demo_flag_on_position()
        {
            var repo = NewRepo();
            repo.UpsertDemo(5, new Position { TokenId = "t1" });

            var pos = repo.FindDemo(5, "t1");
            Assert.NotNull(pos);
            Assert.Equal(5, pos!.AccountId);
            Assert.True(pos.IsDemo);
        }

        [Fact]
        public void Upsert_updates_existing_position_without_duplicating()
        {
            var repo = NewRepo();
            repo.UpsertLive(1, new Position { TokenId = "t1", Size = 10m });
            repo.UpsertLive(1, new Position { TokenId = "t1", Size = 20m });

            var live = repo.GetLive(1);
            Assert.Single(live);
            Assert.Equal(20m, live[0].Size);
        }

        [Fact]
        public void DeleteLive_removes_only_live()
        {
            var repo = NewRepo();
            repo.UpsertLive(1, new Position { TokenId = "t1" });
            repo.UpsertDemo(1, new Position { TokenId = "t1" });

            repo.DeleteLive(1, "t1");

            Assert.Empty(repo.GetLive(1));
            Assert.Single(repo.GetDemo(1));
        }

        [Fact]
        public void DropDemo_clears_only_demo_positions_of_account()
        {
            var repo = NewRepo();
            repo.UpsertDemo(1, new Position { TokenId = "t1" });
            repo.UpsertDemo(1, new Position { TokenId = "t2" });
            repo.UpsertLive(1, new Position { TokenId = "t3" });

            repo.DropDemo(1);

            Assert.Empty(repo.GetDemo(1));
            Assert.Single(repo.GetLive(1));
        }
    }
}
