using System;
using System.Collections.Generic;
using System.Linq;
using ExperionCrawler.Core.Application.Feedforward;
using ExperionCrawler.Infrastructure.Control;
using Xunit;

namespace ExperionCrawler.Tests;

public class FeedforwardBiasTests
{
    private static ColumnConfig Cfg() => new()
    {
        Id = 1, Name = "C-BIAS", Enabled = true, FeedTag = "f", ProductKey = "P",
        ScanSec = 2, BiasMaWindowSec = 20,   // 10 샘플 창
        Streams = new[]
        {
            new StreamConfig { Key = "P", FlowTag = "p", Role = StreamRole.Commanded, Grade = Confidence.A, TargetCoeff = 0.95 },
            new StreamConfig { Key = "D", FlowTag = "d", Role = StreamRole.LevelDriven, Grade = Confidence.B, TargetCoeff = 0.02 },
            new StreamConfig { Key = "B", FlowTag = "b", Role = StreamRole.LevelDriven, Grade = Confidence.B, TargetCoeff = 0.03 },
        }
    };

    // FEED 100 고정, P=95 → K_obs ≈ 0.95, D/B는 물질수지 충족용
    private static PvSnapshot Snap() => new(
        new TagSample("f", 100, true, DateTime.UtcNow), null, Array.Empty<TagSample>(),
        new Dictionary<string, TagSample> {
            ["P"] = new("p", 95, true, DateTime.UtcNow),
            ["D"] = new("d", 2,  true, DateTime.UtcNow),
            ["B"] = new("b", 3,  true, DateTime.UtcNow),
        });

    [Fact]
    public void KObs_and_VLossMa_accumulate_in_steady_state()
    {
        var engine = new FeedforwardEngine();
        var st = new ColumnState();
        AdvisoryResult res = engine.Tick(Cfg(), Snap(), st, DateTime.UtcNow);
        for (int i = 0; i < 20; i++) res = engine.Tick(Cfg(), Snap(), st, DateTime.UtcNow);

        var p = res.Streams.First(s => s.Key == "P");
        Assert.NotNull(p.KObsSuggest);
        Assert.InRange(p.KObsSuggest!.Value, 0.94, 0.96);   // 95/100

        Assert.NotNull(res.VLossMa);
        Assert.InRange(res.VLossMa!.Value, -0.5, 0.5);      // 100-(95+2+3)=0
    }
}
