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 vendor_metrics
const COLUMN_MAP = {
    vendorName: { dbCol: 'vm.vendor_name', type: 'string' },
    productCount: { dbCol: 'vm.product_count', type: 'number' },
    activeProductCount: { dbCol: 'vm.active_product_count', type: 'number' },
    replenishableProductCount: { dbCol: 'vm.replenishable_product_count', type: 'number' },
    currentStockUnits: { dbCol: 'vm.current_stock_units', type: 'number' },
    currentStockCost: { dbCol: 'vm.current_stock_cost', type: 'number' },
    currentStockRetail: { dbCol: 'vm.current_stock_retail', type: 'number' },
    onOrderUnits: { dbCol: 'vm.on_order_units', type: 'number' },
    onOrderCost: { dbCol: 'vm.on_order_cost', type: 'number' },
    poCount365d: { dbCol: 'vm.po_count_365d', type: 'number' },
    avgLeadTimeDays: { dbCol: 'vm.avg_lead_time_days', type: 'number' },
    sales7d: { dbCol: 'vm.sales_7d', type: 'number' },
    revenue7d: { dbCol: 'vm.revenue_7d', type: 'number' },
    sales30d: { dbCol: 'vm.sales_30d', type: 'number' },
    revenue30d: { dbCol: 'vm.revenue_30d', type: 'number' },
    profit30d: { dbCol: 'vm.profit_30d', type: 'number' },
    cogs30d: { dbCol: 'vm.cogs_30d', type: 'number' },
    sales365d: { dbCol: 'vm.sales_365d', type: 'number' },
    revenue365d: { dbCol: 'vm.revenue_365d', type: 'number' },
    lifetimeSales: { dbCol: 'vm.lifetime_sales', type: 'number' },
    lifetimeRevenue: { dbCol: 'vm.lifetime_revenue', type: 'number' },
    avgMargin30d: { dbCol: 'vm.avg_margin_30d', type: 'number' },
    // Growth metrics
    salesGrowth30dVsPrev: { dbCol: 'vm.sales_growth_30d_vs_prev', type: 'number' },
    revenueGrowth30dVsPrev: { dbCol: 'vm.revenue_growth_30d_vs_prev', type: 'number' },
    // Add aliases if needed for frontend compatibility
    name: { dbCol: 'vm.vendor_name', type: 'string' },
    leadTime: { dbCol: 'vm.avg_lead_time_days', type: 'number' },
    // Add status for filtering
    status: { dbCol: 'vendor_status', type: 'string' },
};

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

// --- Route Handlers ---

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

// GET /vendors-aggregate/stats (Overall vendor stats)
router.get('/stats', async (req, res) => {
     const pool = req.app.locals.pool;
     console.log('GET /vendors-aggregate/stats');
     try {
         // Get basic vendor stats from aggregate table
         const { rows: [stats] } = await pool.query(`
            SELECT
                COUNT(*) AS total_vendors,
                SUM(active_product_count) AS total_active_products,
                SUM(current_stock_cost) AS total_stock_value,
                SUM(on_order_cost) AS total_on_order_value,
                AVG(NULLIF(avg_lead_time_days, 0)) AS overall_avg_lead_time
            FROM public.vendor_metrics vm
         `);
         
         // Count active vendors based on criteria (from old vendors.js)
         const { rows: [activeStats] } = await pool.query(`
            SELECT 
                COUNT(DISTINCT CASE 
                    WHEN po_count_365d > 0 
                    THEN vendor_name 
                END) as active_vendors
            FROM public.vendor_metrics
         `);
         
         // Get overall cost metrics from purchase orders
         const { rows: [overallCostMetrics] } = await pool.query(`
            SELECT 
                ROUND((SUM(ordered * po_cost_price)::numeric / NULLIF(SUM(ordered), 0)), 2) as avg_unit_cost,
                ROUND(SUM(ordered * po_cost_price)::numeric, 3) as total_spend
            FROM purchase_orders
            WHERE po_cost_price IS NOT NULL
                AND ordered > 0
                AND vendor IS NOT NULL AND vendor != ''
         `);

         res.json({
             totalVendors: parseInt(stats?.total_vendors || 0),
             activeVendors: parseInt(activeStats?.active_vendors || 0),
             totalActiveProducts: parseInt(stats?.total_active_products || 0),
             totalValue: parseFloat(stats?.total_stock_value || 0),
             totalOnOrderValue: parseFloat(stats?.total_on_order_value || 0),
             avgLeadTime: parseFloat(stats?.overall_avg_lead_time || 0),
             avgUnitCost: parseFloat(overallCostMetrics?.avg_unit_cost || 0),
             totalSpend: parseFloat(overallCostMetrics?.total_spend || 0)
         });
     } catch (error) {
        console.error('Error fetching vendor stats:', error);
        res.status(500).json({ error: 'Failed to fetch vendor stats.' });
     }
});

// GET /vendors-aggregate/ (List vendors)
router.get('/', async (req, res) => {
    const pool = req.app.locals.pool;
    console.log('GET /vendors-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 || 'vendorName'; // Default sort
        const sortColumnInfo = getSafeColumnInfo(sortQueryKey);
        const sortColumn = sortColumnInfo ? sortColumnInfo.dbCol : 'vm.vendor_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 from vendors.js
        const statusCase = `
            CASE 
                WHEN po_count_365d > 0 AND sales_30d > 0 THEN 'active'
                WHEN po_count_365d > 0 THEN 'inactive'
                ELSE 'pending'
            END as vendor_status
        `;
        
        const baseSql = `
            FROM (
                SELECT 
                    vm.*,
                    ${statusCase}
                FROM public.vendor_metrics vm
            ) vm
            ${whereClause}
        `;

        const countSql = `SELECT COUNT(*) AS total ${baseSql}`;
        const dataSql = `
            WITH vendor_data AS (
                SELECT 
                    vm.*,
                    ${statusCase}
                FROM public.vendor_metrics vm
            )
            SELECT 
                vm.*,
                COALESCE(po.avg_unit_cost, 0) as avg_unit_cost,
                COALESCE(po.total_spend, 0) as total_spend
            FROM vendor_data vm
            LEFT JOIN (
                SELECT 
                    vendor,
                    ROUND((SUM(ordered * po_cost_price)::numeric / NULLIF(SUM(ordered), 0)), 2) as avg_unit_cost,
                    ROUND(SUM(ordered * po_cost_price)::numeric, 3) as total_spend
                FROM purchase_orders
                WHERE po_cost_price IS NOT NULL AND ordered > 0
                GROUP BY vendor
            ) po ON vm.vendor_name = po.vendor
            ${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 vendors = 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({
            vendors,
            pagination: { total, pages: Math.ceil(total / limit), currentPage: page, limit },
        });

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

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

export default router;