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 = 5000; // Increase this to allow retrieving all categories in one request

// Maps query keys to DB columns in category_metrics and categories tables
const COLUMN_MAP = {
    categoryId: { dbCol: 'cm.category_id', type: 'integer' },
    categoryName: { dbCol: 'cm.category_name', type: 'string' }, // From aggregate table
    categoryType: { dbCol: 'cm.category_type', type: 'integer' }, // From aggregate table
    parentId: { dbCol: 'cm.parent_id', type: 'integer' }, // From aggregate table
    parentName: { dbCol: 'p.name', type: 'string' }, // Requires JOIN to categories
    productCount: { dbCol: 'cm.product_count', type: 'number' },
    activeProductCount: { dbCol: 'cm.active_product_count', type: 'number' },
    replenishableProductCount: { dbCol: 'cm.replenishable_product_count', type: 'number' },
    currentStockUnits: { dbCol: 'cm.current_stock_units', type: 'number' },
    currentStockCost: { dbCol: 'cm.current_stock_cost', type: 'number' },
    currentStockRetail: { dbCol: 'cm.current_stock_retail', type: 'number' },
    sales7d: { dbCol: 'cm.sales_7d', type: 'number' },
    revenue7d: { dbCol: 'cm.revenue_7d', type: 'number' },
    sales30d: { dbCol: 'cm.sales_30d', type: 'number' },
    revenue30d: { dbCol: 'cm.revenue_30d', type: 'number' },
    profit30d: { dbCol: 'cm.profit_30d', type: 'number' },
    cogs30d: { dbCol: 'cm.cogs_30d', type: 'number' },
    sales365d: { dbCol: 'cm.sales_365d', type: 'number' },
    revenue365d: { dbCol: 'cm.revenue_365d', type: 'number' },
    lifetimeSales: { dbCol: 'cm.lifetime_sales', type: 'number' },
    lifetimeRevenue: { dbCol: 'cm.lifetime_revenue', type: 'number' },
    avgMargin30d: { dbCol: 'cm.avg_margin_30d', type: 'number' },
    stockTurn30d: { dbCol: 'cm.stock_turn_30d', type: 'number' },
    // Growth metrics
    salesGrowth30dVsPrev: { dbCol: 'cm.sales_growth_30d_vs_prev', type: 'number' },
    revenueGrowth30dVsPrev: { dbCol: 'cm.revenue_growth_30d_vs_prev', type: 'number' },
    // Add status from the categories table for filtering
    status: { dbCol: 'c.status', type: 'string' },
};

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

// Type Labels (Consider moving to a shared config or fetching from DB)
const TYPE_LABELS = {
    10: 'Section', 11: 'Category', 12: 'Subcategory', 13: 'Sub-subcategory',
    1: 'Company', 2: 'Line', 3: 'Subline', 40: 'Artist', // From old schema comments
    20: 'Theme', 21: 'Subtheme' // Additional types from categories.js
};

// --- Route Handlers ---

// GET /categories-aggregate/filter-options
router.get('/filter-options', async (req, res) => {
    const pool = req.app.locals.pool;
    console.log('GET /categories-aggregate/filter-options');
    try {
        // Fetch distinct types directly from the aggregate table if reliable
        // Or join with categories table if source of truth is needed
        const { rows: typeRows } = await pool.query(`
            SELECT DISTINCT category_type
            FROM public.category_metrics
            ORDER BY category_type
        `);

        const typeOptions = typeRows.map(r => ({
            value: r.category_type,
            label: TYPE_LABELS[r.category_type] || `Type ${r.category_type}` // Add labels
        }));

        // Add status options for filtering (from categories.js)
        const { rows: statusRows } = await pool.query(`
            SELECT DISTINCT status FROM public.categories ORDER BY status
        `);
        
        // Get type counts (from categories.js)
        const { rows: typeCounts } = await pool.query(`
            SELECT 
                type,
                COUNT(*)::integer as count
            FROM categories
            GROUP BY type
            ORDER BY type
        `);

        res.json({
            types: typeOptions,
            statuses: statusRows.map(r => r.status),
            typeCounts: typeCounts.map(tc => ({
                type: tc.type,
                count: tc.count
            }))
        });
    } catch (error) {
        console.error('Error fetching category filter options:', error);
        res.status(500).json({ error: 'Failed to fetch filter options' });
    }
});

// GET /categories-aggregate/stats
router.get('/stats', async (req, res) => {
     const pool = req.app.locals.pool;
     console.log('GET /categories-aggregate/stats');
     try {
         // Calculate stats directly from the aggregate table
         const { rows: [stats] } = await pool.query(`
            SELECT
                COUNT(*) AS total_categories,
                -- Count active based on the source categories table status
                COUNT(CASE WHEN c.status = 'active' THEN cm.category_id END) AS active_categories,
                SUM(cm.active_product_count) AS total_active_products, -- Sum from aggregates
                SUM(cm.current_stock_cost) AS total_stock_value, -- Sum from aggregates
                -- Weighted Average Margin (Revenue as weight)
                SUM(cm.profit_30d) * 100.0 / NULLIF(SUM(cm.revenue_30d), 0) AS overall_avg_margin_weighted,
                -- Simple Average Margin (less accurate if categories vary greatly in size)
                AVG(NULLIF(cm.avg_margin_30d, 0)) AS overall_avg_margin_simple
                -- Growth rate can be calculated from 30d vs previous 30d revenue if needed
            FROM public.category_metrics cm
            JOIN public.categories c ON cm.category_id = c.cat_id -- Join to check category status
         `);

         res.json({
             totalCategories: parseInt(stats?.total_categories || 0),
             activeCategories: parseInt(stats?.active_categories || 0), // Based on categories.status
             totalActiveProducts: parseInt(stats?.total_active_products || 0),
             totalValue: parseFloat(stats?.total_stock_value || 0),
             // Choose which avg margin calculation to expose
             avgMargin: parseFloat(stats?.overall_avg_margin_weighted || stats?.overall_avg_margin_simple || 0)
             // Growth rate could be added if we implement the calculation
         });
     } catch (error) {
        console.error('Error fetching category stats:', error);
        res.status(500).json({ error: 'Failed to fetch category stats.' });
     }
});

// GET /categories-aggregate/ (List categories)
router.get('/', async (req, res) => {
    const pool = req.app.locals.pool;
    console.log('GET /categories-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 || 'categoryName';
        const sortColumnInfo = getSafeColumnInfo(sortQueryKey);
        
        // Hierarchical sorting logic from categories.js
        const hierarchicalSortOrder = `
            ORDER BY 
                CASE 
                    WHEN cm.category_type = 10 THEN 1  -- sections first
                    WHEN cm.category_type = 11 THEN 2  -- categories second
                    WHEN cm.category_type = 12 THEN 3  -- subcategories third
                    WHEN cm.category_type = 13 THEN 4  -- subsubcategories fourth
                    WHEN cm.category_type = 20 THEN 5  -- themes fifth
                    WHEN cm.category_type = 21 THEN 6  -- subthemes last
                    ELSE 7
                END,
                cm.category_name ASC
        `;
        
        // Use hierarchical sort as default
        let sortClause = hierarchicalSortOrder;
        
        // Override with custom sort if specified
        if (sortColumnInfo && sortQueryKey !== 'categoryName') {
            const sortColumn = sortColumnInfo.dbCol;
            const sortDirection = req.query.order?.toLowerCase() === 'desc' ? 'DESC' : 'ASC';
            const nullsOrder = (sortDirection === 'ASC' ? 'NULLS FIRST' : 'NULLS LAST');
            sortClause = `ORDER BY ${sortColumn} ${sortDirection} ${nullsOrder}`;
        }

        // --- Filtering ---
        const conditions = [];
        const params = [];
        let paramCounter = 1;

        console.log("Starting to process filters from query:", req.query);
        
        // Add filters 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];
            
            console.log(`Processing filter key: "${key}" with value: "${value}"`);

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

            // Special case for parentName requires join
            const requiresJoin = filterKey === 'parentName';
            const columnInfo = getSafeColumnInfo(filterKey);

            if (columnInfo) {
                console.log(`Column info for "${filterKey}":`, columnInfo);
                const dbColumn = columnInfo.dbCol;
                const valueType = columnInfo.type;
                 try {
                    let conditionFragment = '';
                    let needsParam = true;
                    switch (operator.toLowerCase()) {
                        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) {
                         try {
                             // Special handling for categoryType to ensure it works
                             if (filterKey === 'categoryType') {
                                 console.log(`Special handling for categoryType: ${value}`);
                                 // Force conversion to integer
                                 const numericValue = parseInt(value, 10);
                                 if (!isNaN(numericValue)) {
                                     console.log(`Successfully converted categoryType to integer: ${numericValue}`);
                                     conditionFragment = `${dbColumn} ${operator} $${paramCounter++}`;
                                     params.push(numericValue);
                                 } else {
                                     console.error(`Failed to convert categoryType to integer: "${value}"`);
                                     throw new Error(`Invalid categoryType value: "${value}"`);
                                 }
                             } else {
                                 // Normal handling for other fields
                                 const parsedValue = parseValue(value, valueType);
                                 console.log(`Parsed "${value}" as ${valueType}: ${parsedValue}`);
                                 conditionFragment = `${dbColumn} ${operator} $${paramCounter++}`;
                                 params.push(parsedValue);
                             }
                         } catch (innerError) {
                             console.error(`Failed to parse "${value}" as ${valueType}:`, innerError);
                             throw innerError;
                         }
                    } else if (!conditionFragment) { // For LIKE/ILIKE where needsParam is false
                        conditionFragment = `${dbColumn} ${operator} $${paramCounter++}`; // paramCounter was already incremented in push
                    }


                    if (conditionFragment) {
                         console.log(`Adding condition: ${conditionFragment}`);
                         conditions.push(`(${conditionFragment})`);
                    }
                 } catch (parseError) {
                     console.error(`Skipping filter for key "${key}" due to parsing error:`, parseError);
                     if (needsParam) paramCounter--; // Roll back counter if param push failed
                 }
            } else {
                 console.warn(`Invalid filter key ignored: "${key}", not found in COLUMN_MAP`);
            }
        }

        // --- Execute Queries ---
        const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';

        // Need JOIN for parent_name if sorting/filtering by it, or always include for display
        const sortColumn = sortColumnInfo?.dbCol;
        
        // Always include the category and parent joins for status and parent_name
        const joinSql = `
            JOIN public.categories c ON cm.category_id = c.cat_id
            LEFT JOIN public.categories p ON cm.parent_id = p.cat_id
        `;

        const baseSql = `
            FROM public.category_metrics cm
            ${joinSql}
            ${whereClause}
        `;

        const countSql = `SELECT COUNT(*) AS total ${baseSql}`;
        const dataSql = `
            SELECT 
                cm.*,
                c.status,
                c.description,
                p.name as parent_name,
                p.type as parent_type
            ${baseSql}
            ${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 categories = 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({
            categories,
            pagination: { total, pages: Math.ceil(total / limit), currentPage: page, limit },
        });

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

export default router;