-- =====================================================
-- APOLLINARE WAREHOUSE MODULE - DATABASE TABLES
-- SQLite
-- =====================================================

-- Magazzini
CREATE TABLE IF NOT EXISTS WarehouseLocations (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Code TEXT NOT NULL UNIQUE,
    Name TEXT NOT NULL,
    Description TEXT,
    Address TEXT,
    City TEXT,
    Province TEXT,
    PostalCode TEXT,
    Country TEXT DEFAULT 'Italia',
    Type INTEGER NOT NULL DEFAULT 0,
    IsDefault INTEGER NOT NULL DEFAULT 0,
    IsActive INTEGER NOT NULL DEFAULT 1,
    SortOrder INTEGER NOT NULL DEFAULT 0,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT
);

CREATE INDEX IF NOT EXISTS IX_WarehouseLocations_Code ON WarehouseLocations(Code);
CREATE INDEX IF NOT EXISTS IX_WarehouseLocations_IsDefault ON WarehouseLocations(IsDefault);
CREATE INDEX IF NOT EXISTS IX_WarehouseLocations_IsActive ON WarehouseLocations(IsActive);

-- Categorie Articoli
CREATE TABLE IF NOT EXISTS WarehouseArticleCategories (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Code TEXT NOT NULL UNIQUE,
    Name TEXT NOT NULL,
    Description TEXT,
    ParentCategoryId INTEGER,
    Level INTEGER NOT NULL DEFAULT 0,
    FullPath TEXT,
    Icon TEXT,
    Color TEXT,
    DefaultValuationMethod INTEGER,
    SortOrder INTEGER NOT NULL DEFAULT 0,
    IsActive INTEGER NOT NULL DEFAULT 1,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ParentCategoryId) REFERENCES WarehouseArticleCategories(Id) ON DELETE RESTRICT
);

CREATE INDEX IF NOT EXISTS IX_WarehouseArticleCategories_Code ON WarehouseArticleCategories(Code);
CREATE INDEX IF NOT EXISTS IX_WarehouseArticleCategories_ParentCategoryId ON WarehouseArticleCategories(ParentCategoryId);
CREATE INDEX IF NOT EXISTS IX_WarehouseArticleCategories_FullPath ON WarehouseArticleCategories(FullPath);

-- Articoli Magazzino
CREATE TABLE IF NOT EXISTS WarehouseArticles (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Code TEXT NOT NULL UNIQUE,
    Description TEXT NOT NULL,
    ShortDescription TEXT,
    Barcode TEXT,
    ManufacturerCode TEXT,
    CategoryId INTEGER,
    UnitOfMeasure TEXT NOT NULL DEFAULT 'PZ',
    SecondaryUnitOfMeasure TEXT,
    UnitConversionFactor REAL,
    StockManagement INTEGER NOT NULL DEFAULT 0,
    IsBatchManaged INTEGER NOT NULL DEFAULT 0,
    IsSerialManaged INTEGER NOT NULL DEFAULT 0,
    HasExpiry INTEGER NOT NULL DEFAULT 0,
    ExpiryWarningDays INTEGER,
    MinimumStock REAL,
    MaximumStock REAL,
    ReorderPoint REAL,
    ReorderQuantity REAL,
    LeadTimeDays INTEGER,
    ValuationMethod INTEGER,
    StandardCost REAL,
    LastPurchaseCost REAL,
    WeightedAverageCost REAL,
    BaseSellingPrice REAL,
    Weight REAL,
    Volume REAL,
    Width REAL,
    Height REAL,
    Depth REAL,
    Image BLOB,
    ImageMimeType TEXT,
    IsActive INTEGER NOT NULL DEFAULT 1,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (CategoryId) REFERENCES WarehouseArticleCategories(Id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS IX_WarehouseArticles_Code ON WarehouseArticles(Code);
CREATE INDEX IF NOT EXISTS IX_WarehouseArticles_Barcode ON WarehouseArticles(Barcode);
CREATE INDEX IF NOT EXISTS IX_WarehouseArticles_CategoryId ON WarehouseArticles(CategoryId);
CREATE INDEX IF NOT EXISTS IX_WarehouseArticles_IsActive ON WarehouseArticles(IsActive);

-- Partite/Lotti
CREATE TABLE IF NOT EXISTS ArticleBatches (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ArticleId INTEGER NOT NULL,
    BatchNumber TEXT NOT NULL,
    ProductionDate TEXT,
    ExpiryDate TEXT,
    SupplierBatch TEXT,
    SupplierId INTEGER,
    UnitCost REAL,
    InitialQuantity REAL NOT NULL DEFAULT 0,
    CurrentQuantity REAL NOT NULL DEFAULT 0,
    ReservedQuantity REAL NOT NULL DEFAULT 0,
    Status INTEGER NOT NULL DEFAULT 0,
    QualityStatus INTEGER,
    LastQualityCheckDate TEXT,
    Certifications TEXT,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE CASCADE,
    UNIQUE(ArticleId, BatchNumber)
);

CREATE INDEX IF NOT EXISTS IX_ArticleBatches_ArticleId_BatchNumber ON ArticleBatches(ArticleId, BatchNumber);
CREATE INDEX IF NOT EXISTS IX_ArticleBatches_ExpiryDate ON ArticleBatches(ExpiryDate);
CREATE INDEX IF NOT EXISTS IX_ArticleBatches_Status ON ArticleBatches(Status);

-- Seriali/Matricole
CREATE TABLE IF NOT EXISTS ArticleSerials (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ArticleId INTEGER NOT NULL,
    BatchId INTEGER,
    SerialNumber TEXT NOT NULL,
    ManufacturerSerial TEXT,
    ProductionDate TEXT,
    WarrantyExpiryDate TEXT,
    CurrentWarehouseId INTEGER,
    Status INTEGER NOT NULL DEFAULT 0,
    UnitCost REAL,
    SupplierId INTEGER,
    CustomerId INTEGER,
    SoldDate TEXT,
    SalesReference TEXT,
    Attributes TEXT,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE CASCADE,
    FOREIGN KEY (BatchId) REFERENCES ArticleBatches(Id) ON DELETE SET NULL,
    FOREIGN KEY (CurrentWarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE SET NULL,
    UNIQUE(ArticleId, SerialNumber)
);

CREATE INDEX IF NOT EXISTS IX_ArticleSerials_ArticleId_SerialNumber ON ArticleSerials(ArticleId, SerialNumber);
CREATE INDEX IF NOT EXISTS IX_ArticleSerials_Status ON ArticleSerials(Status);
CREATE INDEX IF NOT EXISTS IX_ArticleSerials_CurrentWarehouseId ON ArticleSerials(CurrentWarehouseId);

-- Barcode aggiuntivi
CREATE TABLE IF NOT EXISTS ArticleBarcodes (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ArticleId INTEGER NOT NULL,
    Barcode TEXT NOT NULL UNIQUE,
    Type INTEGER NOT NULL DEFAULT 0,
    Description TEXT,
    Quantity REAL NOT NULL DEFAULT 1,
    IsPrimary INTEGER NOT NULL DEFAULT 0,
    IsActive INTEGER NOT NULL DEFAULT 1,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS IX_ArticleBarcodes_Barcode ON ArticleBarcodes(Barcode);
CREATE INDEX IF NOT EXISTS IX_ArticleBarcodes_ArticleId ON ArticleBarcodes(ArticleId);

-- Giacenze
CREATE TABLE IF NOT EXISTS StockLevels (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ArticleId INTEGER NOT NULL,
    WarehouseId INTEGER NOT NULL,
    BatchId INTEGER,
    Quantity REAL NOT NULL DEFAULT 0,
    ReservedQuantity REAL NOT NULL DEFAULT 0,
    OnOrderQuantity REAL NOT NULL DEFAULT 0,
    StockValue REAL,
    UnitCost REAL,
    LastMovementDate TEXT,
    LastInventoryDate TEXT,
    LocationCode TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE CASCADE,
    FOREIGN KEY (WarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE CASCADE,
    FOREIGN KEY (BatchId) REFERENCES ArticleBatches(Id) ON DELETE SET NULL,
    UNIQUE(ArticleId, WarehouseId, BatchId)
);

CREATE INDEX IF NOT EXISTS IX_StockLevels_ArticleId_WarehouseId_BatchId ON StockLevels(ArticleId, WarehouseId, BatchId);
CREATE INDEX IF NOT EXISTS IX_StockLevels_WarehouseId ON StockLevels(WarehouseId);
CREATE INDEX IF NOT EXISTS IX_StockLevels_LocationCode ON StockLevels(LocationCode);

-- Causali Movimento
CREATE TABLE IF NOT EXISTS MovementReasons (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Code TEXT NOT NULL UNIQUE,
    Description TEXT NOT NULL,
    MovementType INTEGER NOT NULL,
    StockSign INTEGER NOT NULL,
    RequiresExternalReference INTEGER NOT NULL DEFAULT 0,
    RequiresValuation INTEGER NOT NULL DEFAULT 1,
    UpdatesAverageCost INTEGER NOT NULL DEFAULT 1,
    IsSystem INTEGER NOT NULL DEFAULT 0,
    IsActive INTEGER NOT NULL DEFAULT 1,
    SortOrder INTEGER NOT NULL DEFAULT 0,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT
);

CREATE INDEX IF NOT EXISTS IX_MovementReasons_Code ON MovementReasons(Code);
CREATE INDEX IF NOT EXISTS IX_MovementReasons_MovementType ON MovementReasons(MovementType);
CREATE INDEX IF NOT EXISTS IX_MovementReasons_IsActive ON MovementReasons(IsActive);

-- Movimenti di Magazzino (Testata)
CREATE TABLE IF NOT EXISTS StockMovements (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    DocumentNumber TEXT NOT NULL UNIQUE,
    MovementDate TEXT NOT NULL,
    Type INTEGER NOT NULL,
    ReasonId INTEGER,
    SourceWarehouseId INTEGER,
    DestinationWarehouseId INTEGER,
    ExternalReference TEXT,
    ExternalDocumentType INTEGER,
    SupplierId INTEGER,
    CustomerId INTEGER,
    Status INTEGER NOT NULL DEFAULT 0,
    ConfirmedDate TEXT,
    ConfirmedBy TEXT,
    TotalValue REAL,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ReasonId) REFERENCES MovementReasons(Id) ON DELETE SET NULL,
    FOREIGN KEY (SourceWarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE RESTRICT,
    FOREIGN KEY (DestinationWarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE RESTRICT
);

CREATE INDEX IF NOT EXISTS IX_StockMovements_DocumentNumber ON StockMovements(DocumentNumber);
CREATE INDEX IF NOT EXISTS IX_StockMovements_MovementDate ON StockMovements(MovementDate);
CREATE INDEX IF NOT EXISTS IX_StockMovements_Type ON StockMovements(Type);
CREATE INDEX IF NOT EXISTS IX_StockMovements_Status ON StockMovements(Status);
CREATE INDEX IF NOT EXISTS IX_StockMovements_ExternalReference ON StockMovements(ExternalReference);

-- Movimenti di Magazzino (Righe)
CREATE TABLE IF NOT EXISTS StockMovementLines (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    MovementId INTEGER NOT NULL,
    LineNumber INTEGER NOT NULL,
    ArticleId INTEGER NOT NULL,
    BatchId INTEGER,
    SerialId INTEGER,
    Quantity REAL NOT NULL,
    UnitOfMeasure TEXT NOT NULL DEFAULT 'PZ',
    UnitCost REAL,
    LineValue REAL,
    SourceLocationCode TEXT,
    DestinationLocationCode TEXT,
    ExternalLineReference TEXT,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (MovementId) REFERENCES StockMovements(Id) ON DELETE CASCADE,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE RESTRICT,
    FOREIGN KEY (BatchId) REFERENCES ArticleBatches(Id) ON DELETE SET NULL,
    FOREIGN KEY (SerialId) REFERENCES ArticleSerials(Id) ON DELETE SET NULL,
    UNIQUE(MovementId, LineNumber)
);

CREATE INDEX IF NOT EXISTS IX_StockMovementLines_MovementId_LineNumber ON StockMovementLines(MovementId, LineNumber);
CREATE INDEX IF NOT EXISTS IX_StockMovementLines_ArticleId ON StockMovementLines(ArticleId);
CREATE INDEX IF NOT EXISTS IX_StockMovementLines_BatchId ON StockMovementLines(BatchId);
CREATE INDEX IF NOT EXISTS IX_StockMovementLines_SerialId ON StockMovementLines(SerialId);

-- Valorizzazione Magazzino per Periodo
CREATE TABLE IF NOT EXISTS StockValuations (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ValuationDate TEXT NOT NULL,
    Period INTEGER NOT NULL,
    ArticleId INTEGER NOT NULL,
    WarehouseId INTEGER,
    Quantity REAL NOT NULL DEFAULT 0,
    Method INTEGER NOT NULL DEFAULT 0,
    UnitCost REAL NOT NULL DEFAULT 0,
    TotalValue REAL NOT NULL DEFAULT 0,
    InboundQuantity REAL NOT NULL DEFAULT 0,
    InboundValue REAL NOT NULL DEFAULT 0,
    OutboundQuantity REAL NOT NULL DEFAULT 0,
    OutboundValue REAL NOT NULL DEFAULT 0,
    IsClosed INTEGER NOT NULL DEFAULT 0,
    ClosedDate TEXT,
    ClosedBy TEXT,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE CASCADE,
    FOREIGN KEY (WarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE SET NULL,
    UNIQUE(Period, ArticleId, WarehouseId)
);

CREATE INDEX IF NOT EXISTS IX_StockValuations_Period_ArticleId_WarehouseId ON StockValuations(Period, ArticleId, WarehouseId);
CREATE INDEX IF NOT EXISTS IX_StockValuations_ValuationDate ON StockValuations(ValuationDate);
CREATE INDEX IF NOT EXISTS IX_StockValuations_IsClosed ON StockValuations(IsClosed);

-- Layer Valorizzazione FIFO/LIFO
CREATE TABLE IF NOT EXISTS StockValuationLayers (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    ArticleId INTEGER NOT NULL,
    WarehouseId INTEGER NOT NULL,
    BatchId INTEGER,
    LayerDate TEXT NOT NULL,
    SourceMovementId INTEGER,
    OriginalQuantity REAL NOT NULL DEFAULT 0,
    RemainingQuantity REAL NOT NULL DEFAULT 0,
    UnitCost REAL NOT NULL DEFAULT 0,
    IsExhausted INTEGER NOT NULL DEFAULT 0,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE CASCADE,
    FOREIGN KEY (WarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE CASCADE,
    FOREIGN KEY (BatchId) REFERENCES ArticleBatches(Id) ON DELETE SET NULL,
    FOREIGN KEY (SourceMovementId) REFERENCES StockMovements(Id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS IX_StockValuationLayers_ArticleId_WarehouseId_LayerDate ON StockValuationLayers(ArticleId, WarehouseId, LayerDate);
CREATE INDEX IF NOT EXISTS IX_StockValuationLayers_IsExhausted ON StockValuationLayers(IsExhausted);

-- Inventari Fisici (Testata)
CREATE TABLE IF NOT EXISTS InventoryCounts (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    Code TEXT NOT NULL UNIQUE,
    Description TEXT NOT NULL,
    InventoryDate TEXT NOT NULL,
    WarehouseId INTEGER,
    CategoryId INTEGER,
    Type INTEGER NOT NULL DEFAULT 0,
    Status INTEGER NOT NULL DEFAULT 0,
    StartDate TEXT,
    EndDate TEXT,
    ConfirmedDate TEXT,
    ConfirmedBy TEXT,
    AdjustmentMovementId INTEGER,
    PositiveDifferenceValue REAL,
    NegativeDifferenceValue REAL,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (WarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE SET NULL,
    FOREIGN KEY (CategoryId) REFERENCES WarehouseArticleCategories(Id) ON DELETE SET NULL,
    FOREIGN KEY (AdjustmentMovementId) REFERENCES StockMovements(Id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS IX_InventoryCounts_Code ON InventoryCounts(Code);
CREATE INDEX IF NOT EXISTS IX_InventoryCounts_InventoryDate ON InventoryCounts(InventoryDate);
CREATE INDEX IF NOT EXISTS IX_InventoryCounts_Status ON InventoryCounts(Status);

-- Inventari Fisici (Righe)
CREATE TABLE IF NOT EXISTS InventoryCountLines (
    Id INTEGER PRIMARY KEY AUTOINCREMENT,
    InventoryCountId INTEGER NOT NULL,
    ArticleId INTEGER NOT NULL,
    WarehouseId INTEGER NOT NULL,
    BatchId INTEGER,
    LocationCode TEXT,
    TheoreticalQuantity REAL NOT NULL DEFAULT 0,
    CountedQuantity REAL,
    UnitCost REAL,
    CountedAt TEXT,
    CountedBy TEXT,
    SecondCountQuantity REAL,
    SecondCountBy TEXT,
    Notes TEXT,
    CreatedAt TEXT,
    CreatedBy TEXT,
    UpdatedAt TEXT,
    UpdatedBy TEXT,
    FOREIGN KEY (InventoryCountId) REFERENCES InventoryCounts(Id) ON DELETE CASCADE,
    FOREIGN KEY (ArticleId) REFERENCES WarehouseArticles(Id) ON DELETE RESTRICT,
    FOREIGN KEY (WarehouseId) REFERENCES WarehouseLocations(Id) ON DELETE RESTRICT,
    FOREIGN KEY (BatchId) REFERENCES ArticleBatches(Id) ON DELETE SET NULL,
    UNIQUE(InventoryCountId, ArticleId, WarehouseId, BatchId)
);

CREATE INDEX IF NOT EXISTS IX_InventoryCountLines_InventoryCountId_ArticleId ON InventoryCountLines(InventoryCountId, ArticleId, WarehouseId, BatchId);
CREATE INDEX IF NOT EXISTS IX_InventoryCountLines_ArticleId ON InventoryCountLines(ArticleId);
