using CashLineERP.Contracts.Inventory;

namespace CashLineERP.Application.Inventory;

public sealed class InventoryAdjustmentService : IInventoryAdjustmentService
{
    private readonly IInventoryAdjustmentRepository _repository;

    public InventoryAdjustmentService(IInventoryAdjustmentRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<InventoryAdjustmentResponse> GetInventoryAdjustments() =>
        _repository.GetInventoryAdjustments().Select(Map).ToArray();

    public InventoryAdjustmentResponse? GetInventoryAdjustment(long inventoryAdjustmentId)
    {
        var adjustment = _repository.GetInventoryAdjustment(inventoryAdjustmentId);
        return adjustment is null ? null : Map(adjustment);
    }

    public InventoryAdjustmentResponse CreateInventoryAdjustment(CreateInventoryAdjustmentRequest request)
    {
        var adjustment = _repository.Create(new CreateInventoryAdjustmentCommand(
            request.BranchId,
            request.WarehouseId,
            request.AdjustmentDate,
            request.ReasonCode,
            request.Notes,
            request.Lines.Select(line => new CreateInventoryAdjustmentLineCommand(
                line.ItemId,
                line.WarehouseLocationId,
                line.QuantityDelta,
                line.UnitOfMeasureCode,
                line.UnitCost,
                line.StockStatus,
                line.BatchNumber,
                line.SerialNumber,
                line.Notes)).ToArray()));

        return Map(adjustment);
    }

    public InventoryAdjustmentResponse SubmitInventoryAdjustment(long inventoryAdjustmentId, long actorUserId) =>
        Map(_repository.Submit(inventoryAdjustmentId, actorUserId));

    public InventoryAdjustmentResponse ApproveInventoryAdjustment(long inventoryAdjustmentId, long actorUserId) =>
        Map(_repository.Approve(inventoryAdjustmentId, actorUserId));

    public InventoryAdjustmentResponse PostInventoryAdjustment(long inventoryAdjustmentId, long actorUserId) =>
        Map(_repository.Post(inventoryAdjustmentId, actorUserId));

    private static InventoryAdjustmentResponse Map(InventoryAdjustmentDetailView adjustment) =>
        new(
            adjustment.InventoryAdjustmentId,
            adjustment.AdjustmentNumber,
            adjustment.BranchId,
            adjustment.WarehouseId,
            adjustment.AdjustmentDate,
            adjustment.ReasonCode,
            adjustment.Notes,
            adjustment.StatusCode,
            adjustment.TotalAdjustmentAmount,
            adjustment.SubmittedAtUtc,
            adjustment.SubmittedByUserId,
            adjustment.ApprovedAtUtc,
            adjustment.ApprovedByUserId,
            adjustment.PostedAtUtc,
            adjustment.PostedByUserId,
            adjustment.GeneralLedgerBatchId,
            adjustment.Lines.Select(line => new InventoryAdjustmentLineResponse(
                line.InventoryAdjustmentLineId,
                line.LineNumber,
                line.ItemId,
                line.WarehouseLocationId,
                line.QuantityDelta,
                line.UnitOfMeasureCode,
                line.UnitCost,
                line.LineAmount,
                line.StockStatus,
                line.BatchNumber,
                line.SerialNumber,
                line.Notes)).ToArray());
}
