-- Create tables if they don't exist
CREATE TABLE IF NOT EXISTS products (
    product_id BIGINT NOT NULL,
    title VARCHAR(255) NOT NULL,
    SKU VARCHAR(50) NOT NULL,
    created_at TIMESTAMP NULL,
    stock_quantity INT DEFAULT 0,
    price DECIMAL(10, 3) NOT NULL,
    regular_price DECIMAL(10, 3) NOT NULL,
    cost_price DECIMAL(10, 3),
    landing_cost_price DECIMAL(10, 3),
    barcode VARCHAR(50),
    updated_at TIMESTAMP,
    visible BOOLEAN DEFAULT true,
    managing_stock BOOLEAN DEFAULT true,
    replenishable BOOLEAN DEFAULT true,
    vendor VARCHAR(100),
    vendor_reference VARCHAR(100),
    permalink VARCHAR(255),
    categories TEXT,
    image VARCHAR(255),
    brand VARCHAR(100),
    options TEXT,
    tags TEXT,
    moq INT DEFAULT 1,
    uom INT DEFAULT 1,
    PRIMARY KEY (product_id),
    UNIQUE KEY unique_sku (SKU),
    INDEX idx_vendor (vendor),
    INDEX idx_brand (brand)
);

-- Temporary tables for batch metrics processing
CREATE TABLE IF NOT EXISTS temp_sales_metrics (
    product_id BIGINT NOT NULL,
    daily_sales_avg DECIMAL(10,3),
    weekly_sales_avg DECIMAL(10,3),
    monthly_sales_avg DECIMAL(10,3),
    total_revenue DECIMAL(10,3),
    avg_margin_percent DECIMAL(10,3),
    first_sale_date DATE,
    last_sale_date DATE,
    PRIMARY KEY (product_id)
);

CREATE TABLE IF NOT EXISTS temp_purchase_metrics (
    product_id BIGINT NOT NULL,
    avg_lead_time_days INT,
    last_purchase_date DATE,
    last_received_date DATE,
    PRIMARY KEY (product_id)
);

-- New table for product metrics
CREATE TABLE IF NOT EXISTS product_metrics (
    product_id BIGINT NOT NULL,
    last_calculated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    -- Sales velocity metrics
    daily_sales_avg DECIMAL(10,3),
    weekly_sales_avg DECIMAL(10,3),
    monthly_sales_avg DECIMAL(10,3),
    -- Stock metrics
    days_of_inventory INT,
    weeks_of_inventory INT,
    reorder_point INT,
    safety_stock INT,
    -- Financial metrics
    avg_margin_percent DECIMAL(10,3),
    total_revenue DECIMAL(10,3),
    -- Purchase metrics
    avg_lead_time_days INT,
    last_purchase_date DATE,
    last_received_date DATE,
    -- Classification
    abc_class CHAR(1),
    stock_status VARCHAR(20),
    PRIMARY KEY (product_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE
);

-- Optimized indexes for metrics calculations
CREATE INDEX idx_orders_metrics ON orders (product_id, date, canceled, quantity, price);
CREATE INDEX idx_purchase_orders_metrics ON purchase_orders (product_id, date, status, ordered, received);

-- New table for time-based aggregates
CREATE TABLE IF NOT EXISTS product_time_aggregates (
    product_id BIGINT NOT NULL,
    year INT NOT NULL,
    month INT NOT NULL,
    -- Sales metrics
    total_quantity_sold INT DEFAULT 0,
    total_revenue DECIMAL(10,3) DEFAULT 0,
    total_cost DECIMAL(10,3) DEFAULT 0,
    order_count INT DEFAULT 0,
    -- Stock changes
    stock_received INT DEFAULT 0,
    stock_ordered INT DEFAULT 0,
    -- Calculated fields
    avg_price DECIMAL(10,3),
    profit_margin DECIMAL(10,3),
    PRIMARY KEY (product_id, year, month),
    FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE,
    INDEX idx_date (year, month)
);

-- New table for vendor performance
CREATE TABLE IF NOT EXISTS vendor_metrics (
    vendor VARCHAR(100) NOT NULL,
    last_calculated_at TIMESTAMP NOT NULL,
    avg_lead_time_days DECIMAL(10,3),
    on_time_delivery_rate DECIMAL(5,2),
    order_fill_rate DECIMAL(5,2),
    total_orders INT,
    total_late_orders INT,
    PRIMARY KEY (vendor),
    FOREIGN KEY (vendor) REFERENCES products(vendor) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS orders (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    order_number VARCHAR(50) NOT NULL,
    product_id BIGINT NOT NULL,
    SKU VARCHAR(50) NOT NULL,
    date DATE NOT NULL,
    price DECIMAL(10, 3) NOT NULL,
    quantity INT NOT NULL,
    discount DECIMAL(10, 3) DEFAULT 0,
    tax DECIMAL(10, 3) DEFAULT 0,
    tax_included BOOLEAN DEFAULT false,
    shipping DECIMAL(10, 3) DEFAULT 0,
    customer VARCHAR(50) NOT NULL,
    status VARCHAR(20) DEFAULT 'pending',
    payment_method VARCHAR(50),
    shipping_method VARCHAR(50),
    shipping_address TEXT,
    billing_address TEXT,
    canceled BOOLEAN DEFAULT false,
    FOREIGN KEY (product_id) REFERENCES products(product_id),
    FOREIGN KEY (SKU) REFERENCES products(SKU),
    INDEX idx_order_number (order_number),
    INDEX idx_customer (customer),
    INDEX idx_date (date),
    INDEX idx_status (status),
    UNIQUE KEY unique_order_product (order_number, product_id)
);

CREATE TABLE IF NOT EXISTS purchase_orders (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    po_id VARCHAR(50) NOT NULL,
    vendor VARCHAR(100) NOT NULL,
    date DATE NOT NULL,
    expected_date DATE,
    product_id BIGINT NOT NULL,
    sku VARCHAR(50) NOT NULL,
    cost_price DECIMAL(10, 3) NOT NULL,
    status VARCHAR(20) DEFAULT 'pending',
    notes TEXT,
    ordered INT NOT NULL,
    received INT DEFAULT 0,
    received_date DATE,
    FOREIGN KEY (product_id) REFERENCES products(product_id),
    FOREIGN KEY (sku) REFERENCES products(SKU),
    INDEX idx_po_id (po_id),
    INDEX idx_vendor (vendor),
    INDEX idx_status (status),
    UNIQUE KEY unique_po_product (po_id, product_id)
);

-- Create categories table
CREATE TABLE IF NOT EXISTS categories (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY unique_name (name)
);

-- Create product_categories junction table
CREATE TABLE IF NOT EXISTS product_categories (
    product_id BIGINT NOT NULL,
    category_id BIGINT NOT NULL,
    PRIMARY KEY (product_id, category_id),
    FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE,
    FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
    INDEX idx_category (category_id),
    INDEX idx_product (product_id)
);

-- Create views for common calculations
CREATE OR REPLACE VIEW product_sales_trends AS
SELECT 
    p.product_id,
    p.SKU,
    p.title,
    COALESCE(SUM(o.quantity), 0) as total_sold,
    COALESCE(AVG(o.quantity), 0) as avg_quantity_per_order,
    COALESCE(COUNT(DISTINCT o.order_number), 0) as number_of_orders,
    MIN(o.date) as first_sale_date,
    MAX(o.date) as last_sale_date
FROM 
    products p
LEFT JOIN 
    orders o ON p.product_id = o.product_id
WHERE 
    o.canceled = false
GROUP BY 
    p.product_id, p.SKU, p.title;

-- Create view for inventory health
CREATE OR REPLACE VIEW inventory_health AS
SELECT 
    p.product_id,
    p.SKU,
    p.title,
    p.stock_quantity,
    pm.daily_sales_avg,
    pm.days_of_inventory,
    pm.reorder_point,
    pm.safety_stock,
    CASE 
        WHEN p.stock_quantity <= pm.safety_stock THEN 'Critical'
        WHEN p.stock_quantity <= pm.reorder_point THEN 'Reorder'
        WHEN p.stock_quantity > (pm.daily_sales_avg * 90) THEN 'Overstocked'
        ELSE 'Healthy'
    END as stock_status
FROM 
    products p
LEFT JOIN 
    product_metrics pm ON p.product_id = pm.product_id
WHERE 
    p.managing_stock = true; 