using Apollinare.Domain.Entities.Warehouse;

namespace Apollinare.API.Modules.Warehouse.Services;

/// <summary>
/// Interfaccia servizio principale per il modulo Magazzino
/// </summary>
public interface IWarehouseService
{
    // ===============================================
    // ARTICOLI
    // ===============================================
    Task<List<WarehouseArticle>> GetArticlesAsync(ArticleFilter? filter = null);
    Task<WarehouseArticle?> GetArticleByIdAsync(int id);
    Task<WarehouseArticle?> GetArticleByCodeAsync(string code);
    Task<WarehouseArticle?> GetArticleByBarcodeAsync(string barcode);
    Task<WarehouseArticle> CreateArticleAsync(WarehouseArticle article);
    Task<WarehouseArticle> UpdateArticleAsync(WarehouseArticle article);
    Task DeleteArticleAsync(int id);

    // ===============================================
    // CATEGORIE
    // ===============================================
    Task<List<WarehouseArticleCategory>> GetCategoriesAsync(bool includeInactive = false);
    Task<List<WarehouseArticleCategory>> GetCategoryTreeAsync();
    Task<WarehouseArticleCategory?> GetCategoryByIdAsync(int id);
    Task<WarehouseArticleCategory> CreateCategoryAsync(WarehouseArticleCategory category);
    Task<WarehouseArticleCategory> UpdateCategoryAsync(WarehouseArticleCategory category);
    Task DeleteCategoryAsync(int id);

    // ===============================================
    // MAGAZZINI
    // ===============================================
    Task<List<WarehouseLocation>> GetWarehousesAsync(bool includeInactive = false);
    Task<WarehouseLocation?> GetWarehouseByIdAsync(int id);
    Task<WarehouseLocation?> GetDefaultWarehouseAsync();
    Task<WarehouseLocation> CreateWarehouseAsync(WarehouseLocation warehouse);
    Task<WarehouseLocation> UpdateWarehouseAsync(WarehouseLocation warehouse);
    Task DeleteWarehouseAsync(int id);
    Task SetDefaultWarehouseAsync(int id);

    // ===============================================
    // PARTITE (BATCH)
    // ===============================================
    Task<List<ArticleBatch>> GetBatchesAsync(int? articleId = null, BatchStatus? status = null);
    Task<ArticleBatch?> GetBatchByIdAsync(int id);
    Task<ArticleBatch?> GetBatchByNumberAsync(int articleId, string batchNumber);
    Task<ArticleBatch> CreateBatchAsync(ArticleBatch batch);
    Task<ArticleBatch> UpdateBatchAsync(ArticleBatch batch);
    Task<List<ArticleBatch>> GetExpiringBatchesAsync(int daysThreshold = 30);
    Task UpdateBatchStatusAsync(int id, BatchStatus status);

    // ===============================================
    // SERIALI
    // ===============================================
    Task<List<ArticleSerial>> GetSerialsAsync(int? articleId = null, SerialStatus? status = null);
    Task<ArticleSerial?> GetSerialByIdAsync(int id);
    Task<ArticleSerial?> GetSerialByNumberAsync(int articleId, string serialNumber);
    Task<ArticleSerial> CreateSerialAsync(ArticleSerial serial);
    Task<ArticleSerial> UpdateSerialAsync(ArticleSerial serial);
    Task UpdateSerialStatusAsync(int id, SerialStatus status);

    // ===============================================
    // GIACENZE
    // ===============================================
    Task<List<StockLevel>> GetStockLevelsAsync(StockLevelFilter? filter = null);
    Task<StockLevel?> GetStockLevelAsync(int articleId, int warehouseId, int? batchId = null);
    Task<decimal> GetTotalStockAsync(int articleId);
    Task<decimal> GetAvailableStockAsync(int articleId, int? warehouseId = null);
    Task<List<StockLevel>> GetLowStockArticlesAsync();
    Task UpdateStockLevelAsync(int articleId, int warehouseId, decimal quantity, int? batchId = null, decimal? unitCost = null);

    // ===============================================
    // MOVIMENTI
    // ===============================================
    Task<List<StockMovement>> GetMovementsAsync(MovementFilter? filter = null);
    Task<StockMovement?> GetMovementByIdAsync(int id);
    Task<StockMovement?> GetMovementByDocumentNumberAsync(string documentNumber);
    Task<StockMovement> CreateMovementAsync(StockMovement movement);
    Task<StockMovement> UpdateMovementAsync(StockMovement movement);
    Task<StockMovement> ConfirmMovementAsync(int id);
    Task<StockMovement> CancelMovementAsync(int id);
    Task<string> GenerateDocumentNumberAsync(MovementType type);

    // ===============================================
    // CAUSALI
    // ===============================================
    Task<List<MovementReason>> GetMovementReasonsAsync(MovementType? type = null, bool includeInactive = false);
    Task<MovementReason?> GetMovementReasonByIdAsync(int id);
    Task<MovementReason> CreateMovementReasonAsync(MovementReason reason);
    Task<MovementReason> UpdateMovementReasonAsync(MovementReason reason);

    // ===============================================
    // VALORIZZAZIONE
    // ===============================================
    Task<decimal> CalculateArticleValueAsync(int articleId, ValuationMethod? method = null);
    Task<StockValuation> CalculatePeriodValuationAsync(int articleId, int period, int? warehouseId = null);
    Task<List<StockValuation>> GetValuationsAsync(int period, int? warehouseId = null);
    Task ClosePeriodAsync(int period);
    Task<decimal> GetWeightedAverageCostAsync(int articleId);
    Task UpdateWeightedAverageCostAsync(int articleId);

    // ===============================================
    // INVENTARIO
    // ===============================================
    Task<List<InventoryCount>> GetInventoryCountsAsync(InventoryStatus? status = null);
    Task<InventoryCount?> GetInventoryCountByIdAsync(int id);
    Task<InventoryCount> CreateInventoryCountAsync(InventoryCount inventory);
    Task<InventoryCount> UpdateInventoryCountAsync(InventoryCount inventory);
    Task<InventoryCount> StartInventoryCountAsync(int id);
    Task<InventoryCount> CompleteInventoryCountAsync(int id);
    Task<InventoryCount> ConfirmInventoryCountAsync(int id);
    Task<InventoryCount> CancelInventoryCountAsync(int id);
    Task<InventoryCountLine> UpdateCountLineAsync(int lineId, decimal countedQuantity, string? countedBy = null);

    // ===============================================
    // SEED DATA
    // ===============================================
    Task SeedDefaultDataAsync();
}

/// <summary>
/// Filtro per ricerca articoli
/// </summary>
public class ArticleFilter
{
    public string? SearchText { get; set; }
    public int? CategoryId { get; set; }
    public bool? IsActive { get; set; }
    public bool? IsBatchManaged { get; set; }
    public bool? IsSerialManaged { get; set; }
    public StockManagementType? StockManagement { get; set; }
    public bool? HasLowStock { get; set; }
    public int Skip { get; set; } = 0;
    public int Take { get; set; } = 100;
    public string? OrderBy { get; set; }
    public bool OrderDescending { get; set; }
}

/// <summary>
/// Filtro per ricerca giacenze
/// </summary>
public class StockLevelFilter
{
    public int? ArticleId { get; set; }
    public int? WarehouseId { get; set; }
    public int? BatchId { get; set; }
    public int? CategoryId { get; set; }
    public bool? OnlyWithStock { get; set; }
    public bool? OnlyLowStock { get; set; }
    public int Skip { get; set; } = 0;
    public int Take { get; set; } = 100;
}

/// <summary>
/// Filtro per ricerca movimenti
/// </summary>
public class MovementFilter
{
    public DateTime? DateFrom { get; set; }
    public DateTime? DateTo { get; set; }
    public MovementType? Type { get; set; }
    public MovementStatus? Status { get; set; }
    public int? WarehouseId { get; set; }
    public int? ArticleId { get; set; }
    public int? ReasonId { get; set; }
    public string? ExternalReference { get; set; }
    public int Skip { get; set; } = 0;
    public int Take { get; set; } = 100;
    public string? OrderBy { get; set; }
    public bool OrderDescending { get; set; } = true;
}
