using CashLineERP.Application.Inventory;
using CashLineERP.Contracts.Inventory;
using CashLineERP.Infrastructure.Persistence.Repositories;

namespace CashLineERP.Api.Tests;

public sealed class WarehouseTransferServiceQaTests
{
    [Fact]
    public void Warehouse_Transfer_Approval_And_Posting_Create_Transfer_Movement_Traceability()
    {
        using var dbContext = QaDbContextFactory.CreateContext();

        var transferService = new WarehouseTransferService(new WarehouseTransferRepository(dbContext));
        var inventoryMovementService = new InventoryMovementService(new InventoryMovementReadRepository(dbContext));

        var created = transferService.CreateWarehouseTransfer(new CreateWarehouseTransferRequest(
            BranchId: 1,
            FromWarehouseId: 1,
            ToWarehouseId: 2,
            TransferDate: new DateOnly(2026, 5, 14),
            ReasonCode: "REBALANCE",
            Notes: "Warehouse rebalance transfer.",
            Lines:
            [
                new CreateWarehouseTransferLineRequest(1001, 11, 21, 6m, "EA", 24m, "AVAILABLE", "TRF-BATCH-1001-A", null, "Rebalance item 1001"),
                new CreateWarehouseTransferLineRequest(1002, 12, 22, 2m, "BOX", 40m, "AVAILABLE", "TRF-BATCH-1002-A", null, "Rebalance item 1002")
            ]));

        Assert.Equal("DRAFT", created.StatusCode);
        Assert.Equal(8m, created.TotalTransferQuantity);

        var submitted = transferService.SubmitWarehouseTransfer(created.WarehouseTransferId, 51);
        Assert.Equal("SUBMITTED", submitted.StatusCode);

        var selfApprovalError = Assert.Throws<InvalidOperationException>(() =>
            transferService.ApproveWarehouseTransfer(created.WarehouseTransferId, 51));
        Assert.Contains("self-approval", selfApprovalError.Message, StringComparison.OrdinalIgnoreCase);

        var approved = transferService.ApproveWarehouseTransfer(created.WarehouseTransferId, 52);
        Assert.Equal("APPROVED", approved.StatusCode);

        var posted = transferService.PostWarehouseTransfer(created.WarehouseTransferId, 53);
        Assert.Equal("POSTED", posted.StatusCode);

        var movements = inventoryMovementService.GetInventoryMovements()
            .Where(movement => movement.MovementType == "WAREHOUSE_TRANSFER")
            .ToArray();

        Assert.Contains(movements, movement =>
            movement.ItemId == 1001 &&
            movement.FromWarehouseId == 1 &&
            movement.ToWarehouseId == 2 &&
            movement.QuantityMoved == 6m);

        Assert.Contains(movements, movement =>
            movement.ItemId == 1002 &&
            movement.FromWarehouseId == 1 &&
            movement.ToWarehouseId == 2 &&
            movement.QuantityMoved == 2m);
    }
}
