using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Infrastructure.Persistence;

namespace SolutionErp.Infrastructure.Tests.Common;

// Subclass cho test — override column types SQL Server-specific (`nvarchar(max)`)
// về TEXT vì SQLite không hỗ trợ. Identity table inherit từ IdentityDbContext
// dùng kiểu chuẩn nên không cần fix thêm.
public class TestApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : ApplicationDbContext(options)
{
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Replace `nvarchar(max)` / `varchar(max)` → `TEXT` cho SQLite compat.
        foreach (var entity in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var prop in entity.GetProperties())
            {
                var colType = prop.GetColumnType();
                if (colType is not null && colType.Contains("max", StringComparison.OrdinalIgnoreCase))
                {
                    prop.SetColumnType("TEXT");
                }
            }
        }
    }
}

// Fixture build SQLite in-memory ApplicationDbContext mỗi test isolated.
// Pattern: shared connection (open in fixture) + EnsureCreated() từ model.
//
// Tại sao SQLite chứ không InMemory provider?
//   - InMemory không hỗ trợ transactions — code generator dùng IsolationLevel.Serializable
//   - SQLite hỗ trợ transactions thật (BEGIN/COMMIT/ROLLBACK), tuy nhiên IsolationLevel
//     enum value bị provider mapping gracefully (no exception, just default behavior)
//   - Đủ để test format + sequential increment + scope reset, KHÔNG đủ cho test
//     race condition thực (cần SQL Server thật)
public sealed class SqliteDbFixture : IDisposable
{
    private readonly SqliteConnection _connection;
    public TestApplicationDbContext Db { get; }

    public SqliteDbFixture()
    {
        // ":memory:" + shared connection — DB tồn tại đến khi connection close.
        _connection = new SqliteConnection("DataSource=:memory:");
        _connection.Open();

        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseSqlite(_connection)
            .EnableSensitiveDataLogging()
            .Options;

        Db = new TestApplicationDbContext(options);
        Db.Database.EnsureCreated();
    }

    public void Dispose()
    {
        Db.Dispose();
        _connection.Dispose();
    }
}

// Stub IDateTime cho tests deterministic — control thời điểm Year boundary.
public sealed class FixedDateTime(DateTime utcNow) : IDateTime
{
    public DateTime UtcNow { get; set; } = utcNow;
    public DateTime Now => UtcNow;   // simplification — VPS chạy UTC, không bao giờ dùng local time trong tests
}
