using System;
using System.Threading.Tasks;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Predictalytics.Domain.Entities;
using Predictalytics.Domain.Enums;
using Predictalytics.Infrastructure.Data;
using Predictalytics.Infrastructure.Data.Repositories;
using Xunit;

namespace Predictalytics.Application.Tests.Services;

/// <summary>
/// Tests for the market upsert paths (added 2026-07-11).
/// Uses SQLite in-memory (same pattern as TradeRetentionWorkerTests).
/// </summary>
public class MarketRepositoryTests
{
    /// <summary>
    /// The on-demand /markets fetch carries no event tags and classifies markets
    /// as "Other". Such an uninformative update must NOT overwrite a category that
    /// was previously derived from the tag-bearing /events sync — while a
    /// legitimate reclassification (Other → Sports) must still go through.
    /// </summary>
    [Fact]
    public async Task AddOrUpdateAsync_DoesNotOverwriteGoodCategoryWithOther()
    {
        using var connection = new SqliteConnection("DataSource=:memory:");
        connection.Open();
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseSqlite(connection)
            .Options;

        using (var setup = new AppDbContext(options))
        {
            setup.Database.EnsureCreated();
            var ev = new Event { Id = 1, Platform = PlatformType.Polymarket, Slug = "e", Title = "E" };
            setup.Set<Event>().Add(ev);
            setup.Markets.Add(new Market
            {
                Id = 10, EventId = 1, Platform = PlatformType.Polymarket,
                ConditionId = "0xabc", PlatformMarketId = 1L, Question = "Lakers to win?",
                Category = MarketCategory.Sports, Subcategory = "NBA"
            });
            setup.SaveChanges();
        }

        // Act 1: uninformative on-demand update (no tags → Other) must not downgrade.
        using (var ctx = new AppDbContext(options))
        {
            var repo = new MarketRepository(ctx);
            await repo.AddOrUpdateAsync(new Market
            {
                Platform = PlatformType.Polymarket, ConditionId = "0xabc",
                PlatformMarketId = 1L, Question = "Lakers to win?",
                Category = MarketCategory.Other, Subcategory = "Other"
            });
        }

        using (var assertCtx = new AppDbContext(options))
        {
            var market = await assertCtx.Markets.SingleAsync(m => m.ConditionId == "0xabc");
            Assert.Equal(MarketCategory.Sports, market.Category);
            Assert.Equal("NBA", market.Subcategory);
        }

        // Act 2: a real classification must still overwrite an existing "Other".
        using (var ctx = new AppDbContext(options))
        {
            var repo = new MarketRepository(ctx);
            await repo.AddOrUpdateAsync(new Market
            {
                Platform = PlatformType.Polymarket, ConditionId = "0xdef",
                PlatformMarketId = 2L, Question = "Unknown thing?",
                Category = MarketCategory.Other, Subcategory = "Other",
                Event = new Event { Platform = PlatformType.Polymarket, PlatformEventId = 2, Slug = "e2", Title = "E2" }
            });
            await repo.AddOrUpdateAsync(new Market
            {
                Platform = PlatformType.Polymarket, ConditionId = "0xdef",
                PlatformMarketId = 2L, Question = "Unknown thing?",
                Category = MarketCategory.Politics, Subcategory = "Elections"
            });
        }

        using (var assertCtx = new AppDbContext(options))
        {
            var market = await assertCtx.Markets.SingleAsync(m => m.ConditionId == "0xdef");
            Assert.Equal(MarketCategory.Politics, market.Category);
            Assert.Equal("Elections", market.Subcategory);
        }
    }
}
