using Hc900Crawler.Core.Application.Feedforward;

namespace Hc900Crawler.Infrastructure.Control;

public sealed class FeedforwardWriteGuard : IFeedforwardWriteGuard
{
    public WriteCheckResult Check(ColumnConfig cfg, StreamAdvisory adv, StreamConfig sc, AdvisoryResult column, bool manualOverride = false)
    {
        // Monitor는 SP 없음. Commanded는 자동·수동 모두 / LevelDriven(D·B 등 피드결정형)은 운전원 수동 추종일 때만.
        if (adv.Role == StreamRole.Monitor)
            return new WriteCheckResult(false, "Monitor 스트림은 SP 없음");
        if (adv.Role == StreamRole.LevelDriven && !manualOverride)
            return new WriteCheckResult(false, "LevelDriven은 자동쓰기 대상 아님(수동 추종만)");

        // D-1 정정: manualOverride(운전원 버튼)일 때만 AdvisoryOnly를 건너뛴다.
        // 아래 Valid/Grade/Transient/범위/NaN 가드는 manualOverride 여부와 무관하게 항상 적용.
        if (cfg.AdvisoryOnly && !manualOverride)
            return new WriteCheckResult(false, "컬럼이 AdvisoryOnly 모드");

        if (adv.RecommendedSp is not double sp)
            return new WriteCheckResult(false, "권장 SP 없음");

        if (!adv.Valid)
            return new WriteCheckResult(false, "Advisory 무효(전환류 오버라이드 등)");

        if (adv.Grade == Confidence.C)
            return new WriteCheckResult(false, $"신뢰도 C — SP 쓰기 차단");

        if (column.Transient)
            return new WriteCheckResult(false, "과도 상태 — SP 쓰기 차단");

        if (sp < sc.SpMin || sp > sc.SpMax)
            return new WriteCheckResult(false, $"SP {sp:F2} 허용범위 [{sc.SpMin:F2}, {sc.SpMax:F2}] 벗어남");

        if (double.IsNaN(sp) || double.IsInfinity(sp))
            return new WriteCheckResult(false, "SP 값이 NaN/Infinity");

        return new WriteCheckResult(true, null);
    }
}
