using System.Collections;
using Jiaowu.Api.Controllers;
using Jiaowu.Api.Domain.Academic;
using Jiaowu.Api.Domain.Identity;
using Jiaowu.Api.Infrastructure.Auth;
using Jiaowu.Api.Infrastructure.Persistence;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

namespace Jiaowu.Api.Tests;

public sealed class WarningRulePersistenceTests
{
    [Fact]
    public async Task SaveRules_PersistsAutoCheck_AndReturnsNumericType()
    {
        await using var connection = new SqliteConnection("Data Source=:memory:");
        await connection.OpenAsync();
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseSqlite(connection)
            .Options;
        await using var db = new AppDbContext(options);
        await db.Database.EnsureCreatedAsync();
        var term = new AcademicTerm
        {
            Code = "WARN-TERM",
            Name = "预警测试学期",
            AcademicYear = "2026-2027",
            Season = TermSeason.Autumn,
            StartDate = new DateOnly(2026, 9, 1),
            EndDate = new DateOnly(2027, 1, 15)
        };
        db.AcademicTerms.Add(term);
        await db.SaveChangesAsync();
        var controller = new WarningsController(db, new AllDataScope());

        var saveResult = await controller.SaveRules(term.Id,
        [
            new WarningRuleDto(
                WarningType.FailedCredits,
                "不及格学分",
                2m,
                true,
                true,
                true,
                null,
                true,
                1,
                9,
                30)
        ], CancellationToken.None);

        Assert.IsType<NoContentResult>(saveResult);
        db.ChangeTracker.Clear();
        var persisted = Assert.Single(await db.WarningRules.AsNoTracking().ToListAsync());
        Assert.True(persisted.AutoCheckEnabled);
        Assert.Equal(1, persisted.CheckDayOfWeek);
        Assert.Equal(9, persisted.CheckHour);
        Assert.Equal(30, persisted.CheckMinute);

        var getResult = await controller.GetRules(term.Id, CancellationToken.None);
        var ok = Assert.IsType<OkObjectResult>(getResult);
        var row = Assert.Single(Assert.IsAssignableFrom<IEnumerable>(ok.Value).Cast<object>());
        var type = row.GetType().GetProperty("Type")?.GetValue(row);
        Assert.Equal(1, Assert.IsType<int>(type));
    }

    private sealed class AllDataScope : ICurrentUserDataScope
    {
        public CurrentUserScope Current { get; } = new(
            Guid.NewGuid(),
            "测试管理员",
            null,
            DataScope.All,
            new HashSet<string>([SystemRoles.SuperAdmin]));
    }
}
