using GB5Shared.DTO.Framework.Criteria;
using GB5Shared.DTO.Framework.Login;
using GB5Shared.ResponseStandard;
using QMSDAL.DTO;
using System.Data.Common;
namespace QMSDAL.CustomCode.Matrix
{
public interface IMatrixDAL
{
// ── READ — Queries ────────────────────────────────────────────────────
///
/// Returns all matrix headers for the tenant (no MatrixId filter).
/// Inputs and Outputs are NOT populated — call GetAllMatrixInputsAsync /
/// GetAllMatrixOutputsAsync and stitch in the caller.
///
Task> GetAllMatrixHeadersAsync(
LoginDTO login,
CancellationToken ct = default);
/// Returns all input lines for the tenant across all matrices.
Task> GetAllMatrixInputsAsync(
LoginDTO login,
CancellationToken ct = default);
/// Returns all output rows for the tenant across all matrices.
Task> GetAllMatrixOutputsAsync(
LoginDTO login,
CancellationToken ct = default);
///
/// Returns the matrix header. Inputs list is NOT populated here —
/// call GetMatrixInputsAsync separately when lines are needed.
///
Task GetMatrixAsync(
int matrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns all input lines for the given matrix.
///
Task> GetMatrixInputsAsync(
int matrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns all output rows for the given matrix.
/// Used to populate MatrixDTO.Outputs for Mode 2 display and editing.
///
Task> GetMatrixOutputsAsync(
int matrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns true if TMATRIXOUTPUT already has rows for this matrix.
/// Used by ActivateMatrix to skip lot generation when pre-generated.
///
Task HasOutputsGeneratedAsync(
int matrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns Set lot count and FGSerial count generated for
/// this matrix (populated from TMATRIXOUTPUT).
///
Task<(int Sets, int Serials)> GetMatrixOutputCountsAsync(
int matrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns true if allocationId resolves to a real MALLOCATION row.
/// TMATRIX.ALLOCATIONID's FK requires the SO's own header allocation id —
/// NOT a pending-allocation line's AllotedAllocationId.
///
Task AllocationExistsAsync(
int allocationId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns count of rows matching matrixCode for the tenant,
/// excluding the given matrixId (pass 0 for new records).
///
Task CheckDuplicateCodeAsync(
string matrixCode,
int excludeMatrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns true if [setFrom..setTo] overlaps any Active matrix
/// for the given allocation and mode, excluding excludeMatrixId.
/// SetFrom / SetTo use short to match MatrixDTO.
///
Task HasSetRangeOverlapAsync(
int allocationId,
byte matrixMode,
short setFrom,
short setTo,
int excludeMatrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns the next sequential AllocationSlNo for the given
/// allocationId within the tenant.
/// MAX(ALLOCATIONSLNO) + 1, or 1 if none exist yet.
///
Task GetNextAllocationSlNoAsync(
int allocationId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns input lines that have FreeQty below PlannedQty
/// for shortage reporting. FreeQty is populated from stock query.
///
Task> GetStockShortageInputsAsync(
int matrixId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns available RM batches for a given item/SKU,
/// optionally filtered by requiredQty for shortage check.
///
Task> GetAvailableBatchesAsync(
int itemId,
int skuId,
decimal? requiredQty,
LoginDTO login,
CancellationToken ct = default);
///
/// Resolves the MatrixId from a given IndentId via TINDENT.MATRIXID.
/// Returns -1 if not found or not linked.
///
Task GetMatrixIdFromIndentAsync(
int indentId,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns the single input line for a given matrix + item combination.
/// Used at material issue time for batch and qty validation.
/// Returns null if no restriction line exists.
///
Task GetMatrixInputForItemAsync(
int matrixId,
int itemId,
LoginDTO login,
CancellationToken ct = default);
// ── WRITE — Commands (all transactional) ──────────────────────────────
/// Inserts a new TMATRIX header row.
Task> SaveMatrixAsync(
MatrixDTO dto,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
/// Updates an existing TMATRIX header row (Draft only).
Task> UpdateMatrixAsync(
MatrixDTO dto,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Hard-deletes all TMATRIXOUTPUT rows for the given matrixId.
/// Only called for Mode 2 on the update path — Mode 0/1 outputs are immutable.
///
Task> DeleteMatrixOutputsAsync(
int matrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Hard-deletes all TMATRIXINPUT rows for the given matrixId.
/// Safe only on Draft matrices — enforced in BLL before calling.
///
Task> DeleteMatrixInputsAsync(
int matrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Bulk-inserts TMATRIXINPUT rows. IList used (not IEnumerable)
/// because bulk operations require count and index access.
///
Task> BulkSaveMatrixInputsAsync(
IList inputs,
int matrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Soft-deletes a matrix: sets STATUS = 3 (Deleted).
/// Only permitted on Draft matrices — enforced in BLL.
///
Task> SoftDeleteMatrixAsync(
int matrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Marks oldMatrixId as Superseded (MATRIXSTATUS = 2) and
/// sets SUPERSEDEDBYID = newMatrixId on the old row.
///
Task> SupersedeMatrixAsync(
int oldMatrixId,
int newMatrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Updates TMATRIXINPUT.LINESTATUS for all lines of the given matrix
/// after OpenMix (Mode 2) activation:
/// AllocatedQty > 0 → 1 (Partial), otherwise → 0 (Open).
///
Task> ActivateOpenMixInputsAsync(
int matrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Sets MATRIXSTATUS = 1 (Active) and ACTIVATEDON = GETDATE()
/// on the given matrix. Called after Set lots and FGSerials
/// have been generated into TMATRIXOUTPUT.
///
Task> ActivateMatrixAsync(
int matrixId,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Bulk-inserts TLOT rows generated during matrix activation.
/// One row per Set lot or FGSerial depending on MatrixMode.
///
Task> BulkSaveTlotRowsAsync(
IEnumerable lots,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Bulk-inserts TMATRIXOUTPUT rows linking generated lots
/// back to the matrix. Called in the same activation transaction.
///
Task> BulkSaveMatrixOutputsAsync(
IEnumerable outputs,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
///
/// Updates TMATRIXINPUT.CONSUMEDQTY and LINESTATUS
/// for a single input line after a material issue is posted.
///
Task> UpdateConsumedQtyAsync(
int matrixInputId,
decimal additionalQty,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
Task GetSelectListMatrix(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct);
///
/// Matrix-independent picklist joining TPENDINGALLOCATION with MITEM,
/// MBIZTRANSACTIONTYPE, MALLOCATION and MPARTY (via TALLOCATION for quantities).
/// Does not depend on TMATRIX.
///
Task GetSelectListAllocationWithItem(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct);
/// Matrix-independent single allocation-line summary — no TMATRIX.
Task GetAllocationItemSummaryAsync(int allotedAllocationId, LoginDTO login, CancellationToken ct = default);
/// Count of TLOT rows already generated for this item + header allocation — no TMATRIXOUTPUT.
Task GetSetsGeneratedCountAsync(int itemId, int headerAllocationId, LoginDTO login, CancellationToken ct = default);
/// Sets generated for ONE alloted-allocation line only — see GET_SETS_GENERATED_COUNT_FOR_ALLOTED_ALLOCATION.
Task GetSetsGeneratedCountForAllotedAllocationAsync(int itemId, int allotedAllocationId, LoginDTO login, CancellationToken ct = default);
/// The actual SET-level TLOT rows generated for one alloted-allocation line — backs the SetFrom/SetTo picklist.
Task> GetGeneratedSetLotsAsync(int allotedAllocationId, LoginDTO login, CancellationToken ct = default);
/// Reservation policy for a business transaction type — 0=Not Required, 1=Auto, 2=Manual.
Task GetBizTransactionTypeReservationTypeAsync(int bizTransactionTypeId, LoginDTO login, CancellationToken ct = default);
/// Resolves a BizTransactionTypeId by its system code (e.g. "LTPRD"), scoped by tenant + OU. Null if not found.
Task GetBizTransactionTypeIdByCodeAsync(string code, LoginDTO login, CancellationToken ct = default);
/// Resolves an MENTITY.ENTITYID by its ENTITYCODE (e.g. "MATRIX"). Null if not found.
Task GetEntityIdByCodeAsync(string code, LoginDTO login, CancellationToken ct = default);
/// Non-locking read of the current lot sequence — preview/display only.
Task GetLastLotSequencePreviewAsync(string prefix, string suffix, LoginDTO login, CancellationToken ct = default);
/// Current stock + last issued serial per item, from TLOT/TLOTDETAIL only.
Task> GetStockAndLastSerialForItemsAsync(IEnumerable itemIds, LoginDTO login, CancellationToken ct = default);
/// Locking (UPDLOCK, HOLDLOCK) read of the last issued serial for one item — must run inside the caller's transaction.
Task GetLastSerialForItemLockingAsync(int itemId, LoginDTO login, DbTransaction transaction, CancellationToken ct = default);
/// Reserved qty per item, from TRESERVATION only (active reservations).
Task> GetReservedQtyForItemsAsync(IEnumerable itemIds, LoginDTO login, CancellationToken ct = default);
/// Skipped/available serials (TLOT STATUS = 0) for one item — deselected during a prior save.
Task> GetSkippedSerialsAsync(int itemId, LoginDTO login, CancellationToken ct = default);
/// Existing issued serials (TLOT STATUS = 1) for one item — real active stock, pickable to fulfill a run via an existing lot instead of a new one.
Task> GetIssuedSerialsAsync(int itemId, LoginDTO login, CancellationToken ct = default);
/// Free RM stock-on-hand (TSTOCKPOSITION.QUANTITY − RESERVEDQUANTITY, summed across stores) for a set of items.
Task> GetStockOnHandForItemsAsync(IEnumerable itemIds, LoginDTO login, CancellationToken ct = default);
/// Reactivates a previously-skipped serial (TLOT STATUS 0 → 1) in place — user picked it to fulfill the current run instead of issuing a fresh number.
Task> ReactivateSkippedSerialAsync(int lotId, string stockLedgerNumber, DateTime stockLedgerDate, LoginDTO login, DbTransaction tx, CancellationToken ct = default);
/// Resolves a BOM output component's QtyPerSet directly from its own ItemId (no parent product context needed).
Task GetBomOutputQtyPerSetForItemAsync(int itemId, LoginDTO login, CancellationToken ct = default);
// ── BOM Explosion ─────────────────────────────────────────────────────
///
/// Returns BOM component lines (BOMLEVEL != 0) for the given item and planned qty.
/// These form the Input array of the ExplodeBOM response.
///
Task> ExplodeBOMInputsAsync(
int productItemId,
int plannedQty,
LoginDTO login,
CancellationToken ct = default);
///
/// Returns the production item / FG output line (BOMLEVEL = 0) for the given item and planned qty.
/// These form the Output array of the ExplodeBOM response.
///
Task> ExplodeBOMOutputsAsync(
int productItemId,
int plannedQty,
LoginDTO login,
CancellationToken ct = default);
Task GetMatrixSummaryAsync(
int allotedAllocationId, LoginDTO login, CancellationToken ct = default);
Task> BulkSaveTlotDetailRowsAsync(
IEnumerable details, LoginDTO login,
DbTransaction tx, CancellationToken ct = default);
///
/// Bulk-inserts TRESERVATION rows for input lines where IsReservation == false.
/// Each row reserves AllocatedQty of an RM batch against the matrix.
/// Called inside the SaveMatrix transaction so reservations roll back with the header.
///
Task> BulkSaveReservationsAsync(
IEnumerable reservations,
LoginDTO login,
DbTransaction tx,
CancellationToken ct = default);
}
}