-- SESSION-TZ ASSUMPTION: this script runs with TimeZone=America/Chicago
-- (pinned in the pool config and as the inventory_db database default).
-- CURRENT_DATE / NOW()::date / ts::date here mean the BUSINESS date
-- (Chicago calendar day = 1am-Eastern day rule). See docs/TIME.md.
-- Description: Calculates and updates aggregated metrics per brand.
-- Dependencies: product_metrics, products, calculate_status table.
-- Frequency: Daily (after product_metrics update).

DO $$
DECLARE
    _module_name VARCHAR := 'brand_metrics';
    _start_time TIMESTAMPTZ := clock_timestamp();
    _min_revenue NUMERIC := 50.00; -- Minimum revenue threshold for margin calculation
BEGIN
    RAISE NOTICE 'Running % calculation...', _module_name;

    WITH BrandAggregates AS (
        -- Aggregate metrics from product_metrics table per brand
        SELECT
            COALESCE(p.brand, 'Unbranded') AS brand_group, -- Group NULL/empty brands together
            COUNT(DISTINCT pm.pid) AS product_count,
            COUNT(DISTINCT CASE WHEN pm.is_visible THEN pm.pid END) AS active_product_count,
            COUNT(DISTINCT CASE WHEN pm.is_replenishable THEN pm.pid END) AS replenishable_product_count,
            SUM(pm.current_stock) AS current_stock_units,
            SUM(pm.current_stock_cost) AS current_stock_cost,
            SUM(pm.current_stock_retail) AS current_stock_retail,
            -- Only include products with valid sales data in each time period
            COUNT(DISTINCT CASE WHEN pm.sales_7d > 0 THEN pm.pid END) AS products_with_sales_7d,
            SUM(CASE WHEN pm.sales_7d > 0 THEN pm.sales_7d ELSE 0 END) AS sales_7d,
            SUM(COALESCE(pm.revenue_7d, 0)) AS revenue_7d,
            
            COUNT(DISTINCT CASE WHEN pm.sales_30d > 0 THEN pm.pid END) AS products_with_sales_30d,
            SUM(CASE WHEN pm.sales_30d > 0 THEN pm.sales_30d ELSE 0 END) AS sales_30d,
            SUM(COALESCE(pm.revenue_30d, 0)) AS revenue_30d,
            SUM(COALESCE(pm.cogs_30d, 0)) AS cogs_30d,
            SUM(COALESCE(pm.profit_30d, 0)) AS profit_30d,
            
            COUNT(DISTINCT CASE WHEN pm.sales_365d > 0 THEN pm.pid END) AS products_with_sales_365d,
            SUM(CASE WHEN pm.sales_365d > 0 THEN pm.sales_365d ELSE 0 END) AS sales_365d,
            SUM(COALESCE(pm.revenue_365d, 0)) AS revenue_365d,
            
            COUNT(DISTINCT CASE WHEN pm.lifetime_sales > 0 THEN pm.pid END) AS products_with_lifetime_sales,
            SUM(CASE WHEN pm.lifetime_sales > 0 THEN pm.lifetime_sales ELSE 0 END) AS lifetime_sales,
            SUM(COALESCE(pm.lifetime_revenue, 0)) AS lifetime_revenue
        FROM public.product_metrics pm
        JOIN public.products p ON pm.pid = p.pid
        GROUP BY brand_group
    ),
    PreviousPeriodBrandMetrics AS (
        -- Get previous period metrics for growth calculation
        SELECT
            COALESCE(p.brand, 'Unbranded') AS brand_group,
            SUM(CASE WHEN dps.snapshot_date >= CURRENT_DATE - INTERVAL '59 days' 
                     AND dps.snapshot_date < CURRENT_DATE - INTERVAL '29 days' 
                THEN dps.units_sold ELSE 0 END) AS sales_prev_30d,
            SUM(CASE WHEN dps.snapshot_date >= CURRENT_DATE - INTERVAL '59 days' 
                     AND dps.snapshot_date < CURRENT_DATE - INTERVAL '29 days' 
                THEN dps.net_revenue ELSE 0 END) AS revenue_prev_30d
        FROM public.daily_product_snapshots dps
        JOIN public.products p ON dps.pid = p.pid
        GROUP BY brand_group
    ),
    AllBrands AS (
         -- Ensure all brands from products table are included, mapping NULL/empty to 'Unbranded'
        SELECT DISTINCT COALESCE(brand, 'Unbranded') as brand_group
        FROM public.products
    )
    INSERT INTO public.brand_metrics (
        brand_name, last_calculated,
        product_count, active_product_count, replenishable_product_count,
        current_stock_units, current_stock_cost, current_stock_retail,
        sales_7d, revenue_7d, sales_30d, revenue_30d, profit_30d, cogs_30d,
        sales_365d, revenue_365d, lifetime_sales, lifetime_revenue,
        avg_margin_30d,
        sales_growth_30d_vs_prev, revenue_growth_30d_vs_prev
    )
    SELECT
        b.brand_group,
        _start_time,
        -- Base Aggregates
        COALESCE(ba.product_count, 0),
        COALESCE(ba.active_product_count, 0),
        COALESCE(ba.replenishable_product_count, 0),
        COALESCE(ba.current_stock_units, 0),
        COALESCE(ba.current_stock_cost, 0.00),
        COALESCE(ba.current_stock_retail, 0.00),
        -- Sales Aggregates
        COALESCE(ba.sales_7d, 0), COALESCE(ba.revenue_7d, 0.00),
        COALESCE(ba.sales_30d, 0), COALESCE(ba.revenue_30d, 0.00),
        COALESCE(ba.profit_30d, 0.00), COALESCE(ba.cogs_30d, 0.00),
        COALESCE(ba.sales_365d, 0), COALESCE(ba.revenue_365d, 0.00),
        COALESCE(ba.lifetime_sales, 0), COALESCE(ba.lifetime_revenue, 0.00),
        -- KPIs - Calculate margin only for brands with significant revenue
        CASE
            WHEN COALESCE(ba.revenue_30d, 0) >= _min_revenue THEN
                -- Directly calculate margin from revenue and cogs for consistency
                -- This is mathematically equivalent to profit/revenue but more explicit
                ((COALESCE(ba.revenue_30d, 0) - COALESCE(ba.cogs_30d, 0)) / COALESCE(ba.revenue_30d, 1)) * 100.0
            ELSE NULL -- No margin for low/no revenue brands
        END,
        -- Growth metrics
        std_numeric(safe_divide((ba.sales_30d - ppbm.sales_prev_30d) * 100.0, ppbm.sales_prev_30d), 2),
        std_numeric(safe_divide((ba.revenue_30d - ppbm.revenue_prev_30d) * 100.0, ppbm.revenue_prev_30d), 2)
    FROM AllBrands b
    LEFT JOIN BrandAggregates ba ON b.brand_group = ba.brand_group
    LEFT JOIN PreviousPeriodBrandMetrics ppbm ON b.brand_group = ppbm.brand_group

    ON CONFLICT (brand_name) DO UPDATE SET
        last_calculated = EXCLUDED.last_calculated,
        product_count = EXCLUDED.product_count,
        active_product_count = EXCLUDED.active_product_count,
        replenishable_product_count = EXCLUDED.replenishable_product_count,
        current_stock_units = EXCLUDED.current_stock_units,
        current_stock_cost = EXCLUDED.current_stock_cost,
        current_stock_retail = EXCLUDED.current_stock_retail,
        sales_7d = EXCLUDED.sales_7d, revenue_7d = EXCLUDED.revenue_7d,
        sales_30d = EXCLUDED.sales_30d, revenue_30d = EXCLUDED.revenue_30d,
        profit_30d = EXCLUDED.profit_30d, cogs_30d = EXCLUDED.cogs_30d,
        sales_365d = EXCLUDED.sales_365d, revenue_365d = EXCLUDED.revenue_365d,
        lifetime_sales = EXCLUDED.lifetime_sales, lifetime_revenue = EXCLUDED.lifetime_revenue,
        avg_margin_30d = EXCLUDED.avg_margin_30d,
        sales_growth_30d_vs_prev = EXCLUDED.sales_growth_30d_vs_prev,
        revenue_growth_30d_vs_prev = EXCLUDED.revenue_growth_30d_vs_prev
    WHERE -- Only update if at least one value has changed
        brand_metrics.product_count IS DISTINCT FROM EXCLUDED.product_count OR
        brand_metrics.active_product_count IS DISTINCT FROM EXCLUDED.active_product_count OR
        brand_metrics.current_stock_units IS DISTINCT FROM EXCLUDED.current_stock_units OR
        brand_metrics.sales_30d IS DISTINCT FROM EXCLUDED.sales_30d OR
        brand_metrics.revenue_30d IS DISTINCT FROM EXCLUDED.revenue_30d OR
        brand_metrics.lifetime_sales IS DISTINCT FROM EXCLUDED.lifetime_sales OR
        -- Cost revisions can change profit/cogs with unchanged sales/revenue
        brand_metrics.profit_30d IS DISTINCT FROM EXCLUDED.profit_30d OR
        brand_metrics.cogs_30d IS DISTINCT FROM EXCLUDED.cogs_30d;

    -- Update calculate_status
    INSERT INTO public.calculate_status (module_name, last_calculation_timestamp)
    VALUES (_module_name, _start_time)
    ON CONFLICT (module_name) DO UPDATE SET last_calculation_timestamp = _start_time;

    RAISE NOTICE 'Finished % calculation. Duration: %', _module_name, clock_timestamp() - _start_time;
END $$;

-- Return metrics about the update operation for tracking
WITH update_stats AS (
    SELECT 
        COUNT(*) as total_brands,
        COUNT(*) FILTER (WHERE last_calculated >= NOW() - INTERVAL '5 minutes') as rows_processed,
        SUM(product_count) as total_products,
        SUM(active_product_count) as total_active_products,
        SUM(sales_30d) as total_sales_30d,
        SUM(revenue_30d) as total_revenue_30d,
        AVG(avg_margin_30d) as overall_avg_margin_30d
    FROM public.brand_metrics
)
SELECT 
    rows_processed,
    total_brands,
    total_products::int,
    total_active_products::int,
    total_sales_30d::int,
    ROUND(total_revenue_30d, 2) as total_revenue_30d,
    ROUND(overall_avg_margin_30d, 2) as overall_avg_margin_30d
FROM update_stats;