using System.Windows.Forms;
using OpenNest.Data;
using OpenNest.Data.MaterialLedger;
using OpenNest.Forms;
namespace OpenNest.WinForms.Tests.Forms;
///
/// Save and post re-check a nest's ledger item codes: taken codes are listed and the
/// programmer goes on, removes them (one undoable edit) or cancels; a ledger that cannot be
/// read never blocks.
///
public class LedgerCodeRecheckTests
{
[Fact]
public void Proceed_KeepsTheCodesAndRecordsNothing() => UndoTestEnv.Run(env =>
{
var fake = new Fakes { Answer = LedgerCodeRecheck.Choice.Proceed };
var before = UndoTestEnv.Describe(env.Nest);
var count = env.Editor.History.UndoCount;
Assert.True(Confirm(fake, env, "Post"));
Assert.Equal(before, UndoTestEnv.Describe(env.Nest));
Assert.Equal(count, env.Editor.History.UndoCount);
Assert.Equal("Post", fake.AskedAction);
Assert.Equal(
[(1, "B-1", "Only 1 of the 2 sheets needed free in MaterialLedger"), (2, "S-1", "On nest 2026-0042")],
fake.Asked!.Select(c => (c.PlateNumber, c.ItemCode, c.Reason)));
}, CodedNest);
[Fact]
public void RemoveCodes_IsOneUndoableEditThatKeepsTheLayout() => UndoTestEnv.Run(env =>
{
var fake = new Fakes { Answer = LedgerCodeRecheck.Choice.RemoveCodes };
var parts = env.Nest.Plates.Sum(p => p.Parts.Count);
env.AssertOneUndoableEdit(LedgerCodeRecheck.RemoveLabel, () => Assert.True(Confirm(fake, env, "Save")));
Assert.Equal(parts, env.Nest.Plates.Sum(p => p.Parts.Count));
Assert.Equal(2, env.Nest.Plates[0].Quantity);
Assert.Empty(env.Nest.Plates[0].StockItemCodes);
Assert.Equal(["KEEP-1"], env.Nest.Plates[3].StockItemCodes);
Assert.Equal("Removed 2 ledger item codes from 3 sheets", fake.Status);
}, CodedNest);
[Fact]
public void Cancel_StopsTheAttemptAndChangesNothing() => UndoTestEnv.Run(env =>
{
var fake = new Fakes { Answer = LedgerCodeRecheck.Choice.Cancel };
var before = UndoTestEnv.Describe(env.Nest);
Assert.False(Confirm(fake, env, "Save"));
Assert.Equal(before, UndoTestEnv.Describe(env.Nest));
Assert.Equal("Save cancelled", fake.Status);
}, CodedNest);
[Fact]
public void UnreachableLedger_SkipsTheCheckWithANote() => UndoTestEnv.Run(env =>
{
var fake = new Fakes { Stock = new LedgerStockResult.Unreachable("No answer within 5 s.") };
Assert.True(Confirm(fake, env, "Save"));
Assert.Null(fake.Asked);
Assert.Equal("Ledger codes not re-checked: MaterialLedger unreachable (No answer within 5 s.)", fake.Status);
var failing = new Fakes { StockError = new HttpRequestException("refused") };
Assert.True(Confirm(failing, env, "Post"));
Assert.Null(failing.Asked);
Assert.Equal("Ledger codes not re-checked: refused", failing.Status);
}, CodedNest);
[Fact]
public void NoLedgerOrNoCodes_ChecksNothing() => UndoTestEnv.Run(env =>
{
var unconfigured = new Fakes { Configured = false };
Assert.True(Confirm(unconfigured, env, "Save"));
Assert.Equal(0, unconfigured.Fetches);
Assert.Null(unconfigured.Status);
foreach (var plate in env.Nest.Plates)
plate.StockItemCodes = [];
var uncoded = new Fakes();
Assert.True(Confirm(uncoded, env, "Save"));
Assert.Equal(0, uncoded.Fetches);
}, CodedNest);
[Fact]
public void OtherNestsUnknown_ChecksTheLedgerAloneAndSaysSo() => UndoTestEnv.Run(env =>
{
var fake = new Fakes
{
Stock = Free(("B-1", 2), ("S-1", 1), ("KEEP-1", 1)),
InUse = LedgerCodesInUse.Unknown("nests are saved as files"),
};
Assert.True(Confirm(fake, env, "Save"));
Assert.Null(fake.Asked);
Assert.Equal("Ledger codes checked against MaterialLedger only; other nests not checked: nests are saved as files", fake.Status);
}, CodedNest);
[Fact]
public void Dialog_GoesOnOnlyAfterTheAcknowledgement() => StaTestThread.Run(() =>
{
LedgerCodeConflict[] conflicts = [new(1, "B-1", "Not free in MaterialLedger")];
using (var form = new LedgerCodeConflictForm("Post", conflicts))
{
form.Show();
var proceed = Find