import express from 'express';
import { parseValue } from '../utils/apiHelpers.js'; // Adjust path if needed
const router = express.Router();

// --- Configuration & Helpers ---
const DEFAULT_PAGE_LIMIT = 50;
const MAX_PAGE_LIMIT = 200;

// Maps query keys to DB columns in brand_metrics
const COLUMN_MAP = {
    brandName: { dbCol: 'bm.brand_name', type: 'string' },
    productCount: { dbCol: 'bm.product_count', type: 'number' },
    activeProductCount: { dbCol: 'bm.active_product_count', type: 'number' },
    replenishableProductCount: { dbCol: 'bm.replenishable_product_count', type: 'number' },
    currentStockUnits: { dbCol: 'bm.current_stock_units', type: 'number' },
    currentStockCost: { dbCol: 'bm.current_stock_cost', type: 'number' },
    currentStockRetail: { dbCol: 'bm.current_stock_retail', type: 'number' },
    sales7d: { dbCol: 'bm.sales_7d', type: 'number' },
    revenue7d: { dbCol: 'bm.revenue_7d', type: 'number' },
    sales30d: { dbCol: 'bm.sales_30d', type: 'number' },
    revenue30d: { dbCol: 'bm.revenue_30d', type: 'number' },
    profit30d: { dbCol: 'bm.profit_30d', type: 'number' },
    cogs30d: { dbCol: 'bm.cogs_30d', type: 'number' },
    sales365d: { dbCol: 'bm.sales_365d', type: 'number' },
    revenue365d: { dbCol: 'bm.revenue_365d', type: 'number' },
    lifetimeSales: { dbCol: 'bm.lifetime_sales', type: 'number' },
    lifetimeRevenue: { dbCol: 'bm.lifetime_revenue', type: 'number' },
    avgMargin30d: { dbCol: 'bm.avg_margin_30d', type: 'number' },
    // Growth metrics
    salesGrowth30dVsPrev: { dbCol: 'bm.sales_growth_30d_vs_prev', type: 'number' },
    revenueGrowth30dVsPrev: { dbCol: 'bm.revenue_growth_30d_vs_prev', type: 'number' },
    // Add aliases if needed
    name: { dbCol: 'bm.brand_name', type: 'string' },
    // Add status for filtering
    status: { dbCol: 'brand_status', type: 'string' },
};

function getSafeColumnInfo(queryParamKey) {
    return COLUMN_MAP[queryParamKey] || null;
}

// --- Route Handlers ---

// GET /brands-aggregate/filter-options (Just brands list for now)
router.get('/filter-options', async (req, res) => {
    const pool = req.app.locals.pool;
    console.log('GET /brands-aggregate/filter-options');
    try {
        // Get brand names
        const { rows: brandRows } = await pool.query(`
            SELECT DISTINCT brand_name FROM public.brand_metrics ORDER BY brand_name
        `);
        
        // Get status values - calculate them since they're derived
        const { rows: statusRows } = await pool.query(`
            SELECT DISTINCT
                CASE 
                    WHEN active_product_count > 0 AND sales_30d > 0 THEN 'active'
                    WHEN active_product_count > 0 THEN 'inactive'
                    ELSE 'pending'
                END as status
            FROM public.brand_metrics
            ORDER BY status
        `);
        
        res.json({
            brands: brandRows.map(r => r.brand_name),
            statuses: statusRows.map(r => r.status)
        });
     } catch(error) {
        console.error('Error fetching brand filter options:', error);
        res.status(500).json({ error: 'Failed to fetch filter options' });
     }
});

// GET /brands-aggregate/stats (Overall brand stats)
router.get('/stats', async (req, res) => {
     const pool = req.app.locals.pool;
     console.log('GET /brands-aggregate/stats');
     try {
         const { rows: [stats] } = await pool.query(`
            SELECT
                COUNT(*) AS total_brands,
                COUNT(CASE WHEN active_product_count > 0 THEN 1 END) AS active_brands,
                SUM(active_product_count) AS total_active_products,
                SUM(current_stock_cost) AS total_stock_value,
                -- Weighted Average Margin
                SUM(profit_30d) * 100.0 / NULLIF(SUM(revenue_30d), 0) AS overall_avg_margin_weighted
            FROM public.brand_metrics bm
         `);

         res.json({
             totalBrands: parseInt(stats?.total_brands || 0),
             activeBrands: parseInt(stats?.active_brands || 0),
             totalActiveProducts: parseInt(stats?.total_active_products || 0),
             totalValue: parseFloat(stats?.total_stock_value || 0),
             avgMargin: parseFloat(stats?.overall_avg_margin_weighted || 0),
         });
     } catch (error) {
        console.error('Error fetching brand stats:', error);
        res.status(500).json({ error: 'Failed to fetch brand stats.' });
     }
});

// GET /brands-aggregate/ (List brands)
router.get('/', async (req, res) => {
    const pool = req.app.locals.pool;
    console.log('GET /brands-aggregate received query:', req.query);
    try {
        // --- Pagination ---
        let page = parseInt(req.query.page, 10) || 1;
        let limit = parseInt(req.query.limit, 10) || DEFAULT_PAGE_LIMIT;
        limit = Math.min(limit, MAX_PAGE_LIMIT);
        const offset = (page - 1) * limit;

        // --- Sorting ---
        const sortQueryKey = req.query.sort || 'brandName'; // Default sort
        const sortColumnInfo = getSafeColumnInfo(sortQueryKey);
        const sortColumn = sortColumnInfo ? sortColumnInfo.dbCol : 'bm.brand_name';
        const sortDirection = req.query.order?.toLowerCase() === 'desc' ? 'DESC' : 'ASC';
        const nullsOrder = (sortDirection === 'ASC' ? 'NULLS FIRST' : 'NULLS LAST');
        const sortClause = `ORDER BY ${sortColumn} ${sortDirection} ${nullsOrder}`;

        // --- Filtering ---
        const conditions = [];
        const params = [];
        let paramCounter = 1;
        // Build conditions based on req.query, using COLUMN_MAP and parseValue
        for (const key in req.query) {
             if (['page', 'limit', 'sort', 'order'].includes(key)) continue;

             let filterKey = key;
             let operator = '='; // Default operator
             const value = req.query[key];

             const operatorMatch = key.match(/^(.*)_(eq|ne|gt|gte|lt|lte|like|ilike|between|in)$/);
             if (operatorMatch) {
                 filterKey = operatorMatch[1];
                 operator = operatorMatch[2];
             }

             const columnInfo = getSafeColumnInfo(filterKey);
             if (columnInfo) {
                 const dbColumn = columnInfo.dbCol;
                 const valueType = columnInfo.type;
                  try {
                     let conditionFragment = '';
                     let needsParam = true;
                     switch (operator.toLowerCase()) { // Normalize operator
                          case 'eq': operator = '='; break;
                          case 'ne': operator = '<>'; break;
                          case 'gt': operator = '>'; break;
                          case 'gte': operator = '>='; break;
                          case 'lt': operator = '<'; break;
                          case 'lte': operator = '<='; break;
                          case 'like': operator = 'LIKE'; needsParam=false; params.push(`%${parseValue(value, valueType)}%`); break;
                          case 'ilike': operator = 'ILIKE'; needsParam=false; params.push(`%${parseValue(value, valueType)}%`); break;
                          case 'between':
                              const [val1, val2] = String(value).split(',');
                              if (val1 !== undefined && val2 !== undefined) {
                                  conditionFragment = `${dbColumn} BETWEEN $${paramCounter++} AND $${paramCounter++}`;
                                  params.push(parseValue(val1, valueType), parseValue(val2, valueType));
                                  needsParam = false;
                              } else continue;
                              break;
                          case 'in':
                               const inValues = String(value).split(',');
                               if (inValues.length > 0) {
                                  const placeholders = inValues.map(() => `$${paramCounter++}`).join(', ');
                                  conditionFragment = `${dbColumn} IN (${placeholders})`;
                                  params.push(...inValues.map(v => parseValue(v, valueType)));
                                  needsParam = false;
                               } else continue;
                               break;
                          default: operator = '='; break;
                     }

                     if (needsParam) {
                          conditionFragment = `${dbColumn} ${operator} $${paramCounter++}`;
                          params.push(parseValue(value, valueType));
                     } else if (!conditionFragment) { // For LIKE/ILIKE
                          conditionFragment = `${dbColumn} ${operator} $${paramCounter++}`;
                     }


                     if (conditionFragment) {
                          conditions.push(`(${conditionFragment})`);
                     }
                  } catch (parseError) {
                      console.warn(`Skipping filter for key "${key}" due to parsing error: ${parseError.message}`);
                      if (needsParam) paramCounter--;
                  }
             } else {
                  console.warn(`Invalid filter key ignored: ${key}`);
             }
         }


        // --- Execute Queries ---
        const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
        
        // Status calculation similar to vendors
        const statusCase = `
            CASE 
                WHEN active_product_count > 0 AND sales_30d > 0 THEN 'active'
                WHEN active_product_count > 0 THEN 'inactive'
                ELSE 'pending'
            END as brand_status
        `;
        
        const baseSql = `
            FROM (
                SELECT 
                    bm.*,
                    ${statusCase}
                FROM public.brand_metrics bm
            ) bm
            ${whereClause}
        `;

        const countSql = `SELECT COUNT(*) AS total ${baseSql}`;
        const dataSql = `
            WITH brand_data AS (
                SELECT 
                    bm.*,
                    ${statusCase}
                FROM public.brand_metrics bm
            )
            SELECT bm.*
            FROM brand_data bm
            ${whereClause}
            ${sortClause}
            LIMIT $${paramCounter} OFFSET $${paramCounter + 1}
        `;
        const dataParams = [...params, limit, offset];

        console.log("Count SQL:", countSql, params);
        console.log("Data SQL:", dataSql, dataParams);

        const [countResult, dataResult] = await Promise.all([
            pool.query(countSql, params),
            pool.query(dataSql, dataParams)
        ]);

        const total = parseInt(countResult.rows[0].total, 10);
        const brands = dataResult.rows.map(row => {
            // Create a new object with both snake_case and camelCase keys
            const transformedRow = { ...row }; // Start with original data
            
            for (const key in row) {
                // Skip null/undefined values
                if (row[key] === null || row[key] === undefined) {
                    continue; // Original already has the null value
                }

                // Transform keys to match frontend expectations (add camelCase versions)
                // First handle cases like sales_7d -> sales7d
                let camelKey = key.replace(/_(\d+[a-z])/g, '$1');
                
                // Then handle regular snake_case -> camelCase
                camelKey = camelKey.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
                if (camelKey !== key) { // Only add if different from original
                    transformedRow[camelKey] = row[key];
                }
            }
            return transformedRow;
        });

        // --- Respond ---
        res.json({
            brands,
            pagination: { total, pages: Math.ceil(total / limit), currentPage: page, limit },
        });

    } catch (error) {
        console.error('Error fetching brand metrics list:', error);
        res.status(500).json({ error: 'Failed to fetch brand metrics.' });
    }
});

// GET /brands-aggregate/:name (Get single brand metric)
// Implement if needed, remember to URL-decode the name parameter

export default router;