import express from 'express';
import { businessNow } from '../../shared/business-time/index.js';
const router = express.Router();

// Status code constants
// Frontend uses these numeric codes but database uses strings
const STATUS = {
  CANCELED: 0,
  CREATED: 1,
  ELECTRONICALLY_READY_SEND: 10,
  ORDERED: 11,
  PREORDERED: 12,
  ELECTRONICALLY_SENT: 13,
  RECEIVING_STARTED: 15,
  DONE: 50,
  // Receiving status codes
  RECEIVING_CREATED: 1,
  RECEIVING_PARTIAL: 30,
  RECEIVING_FULL: 40,
  RECEIVING_PAID: 50
};

// Status mapping from database string values to frontend numeric codes
const STATUS_MAPPING = {
  'canceled': STATUS.CANCELED,
  'created': STATUS.CREATED,
  'electronically_ready_send': STATUS.ELECTRONICALLY_READY_SEND,
  'ordered': STATUS.ORDERED,
  'preordered': STATUS.PREORDERED,
  'electronically_sent': STATUS.ELECTRONICALLY_SENT,
  'receiving_started': STATUS.RECEIVING_STARTED,
  'done': STATUS.DONE,
  // Receiving status mappings
  'partial_received': STATUS.RECEIVING_PARTIAL,
  'full_received': STATUS.RECEIVING_FULL,
  'paid': STATUS.RECEIVING_PAID
};

// Helper for SQL status value comparison with string values in DB
function getStatusWhereClause(statusNum) {
  const dbStatuses = Object.keys(STATUS_MAPPING).filter(key => 
    STATUS_MAPPING[key] === parseInt(statusNum));
  
  if (dbStatuses.length > 0) {
    return `po.status = '${dbStatuses[0]}'`;
  }
  return `1=0`;  // No match found, return false condition
}

// Get all purchase orders with summary metrics
router.get('/', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    // Parse query parameters with defaults
    const { 
      search = '', 
      status = 'all', 
      vendor = 'all', 
      recordType = 'all',
      startDate = null, 
      endDate = null, 
      page = 1, 
      limit = 100, 
      sortColumn = 'id', 
      sortDirection = 'desc' 
    } = req.query;
    
    console.log("Received query parameters:", {
      search, status, vendor, recordType, page, limit, sortColumn, sortDirection
    });
    
    // Base where clause for purchase orders
    let poWhereClause = '1=1';
    // Base where clause for receivings (used in the receiving_data CTE)
    let receivingWhereClause = '1=1';
    const params = [];
    let paramCounter = 1;
    
    if (search && search.trim() !== '') {
      // Simplified search for purchase orders - improved performance
      const searchTerm = `%${search.trim()}%`;
      poWhereClause += ` AND (
        po.po_id::text ILIKE $${paramCounter} 
        OR po.vendor ILIKE $${paramCounter}
        OR po.notes ILIKE $${paramCounter}
      )`;
      params.push(searchTerm);
      paramCounter++;
      
      // Add search for receivings
      receivingWhereClause += ` AND (
        r.receiving_id::text ILIKE $${paramCounter} 
        OR r.vendor ILIKE $${paramCounter}
      )`;
      params.push(searchTerm);
      paramCounter++;
    }
    
    if (status && status !== 'all') {
      poWhereClause += ` AND ${getStatusWhereClause(status)}`;
      
      // Handle status for receivings
      const dbStatuses = Object.keys(STATUS_MAPPING).filter(key => 
        STATUS_MAPPING[key] === parseInt(status));
      
      if (dbStatuses.length > 0) {
        receivingWhereClause += ` AND r.status = '${dbStatuses[0]}'`;
      }
    }
    
    if (vendor && vendor !== 'all') {
      poWhereClause += ` AND po.vendor = $${paramCounter}`;
      params.push(vendor);
      paramCounter++;
      
      // Add vendor filter for receivings
      receivingWhereClause += ` AND r.vendor = $${paramCounter}`;
      params.push(vendor);
      paramCounter++;
    }
    
    if (startDate) {
      poWhereClause += ` AND po.date >= $${paramCounter}::date`;
      params.push(startDate);
      paramCounter++;
      
      // Add date filter for receivings
      receivingWhereClause += ` AND r.received_date >= $${paramCounter}::date`;
      params.push(startDate);
      paramCounter++;
    }
    
    if (endDate) {
      poWhereClause += ` AND po.date <= $${paramCounter}::date`;
      params.push(endDate);
      paramCounter++;
      
      // Add date filter for receivings
      receivingWhereClause += ` AND r.received_date <= $${paramCounter}::date`;
      params.push(endDate);
      paramCounter++;
    }

    // Get filtered summary metrics
    const summaryQuery = `
      WITH po_totals AS (
        SELECT 
          po_id,
          SUM(ordered) as total_ordered,
          ROUND(SUM(ordered * po_cost_price)::numeric, 3) as total_cost
        FROM purchase_orders po
        WHERE ${poWhereClause}
        GROUP BY po_id
      ),
      receiving_totals AS (
        SELECT 
          r.receiving_id as po_id,
          SUM(r.qty_each) as total_received
        FROM receivings r
        WHERE (${receivingWhereClause})
          AND r.receiving_id IN (SELECT po_id FROM po_totals)
        GROUP BY r.receiving_id
      )
      SELECT 
        COUNT(DISTINCT po.po_id) as order_count,
        SUM(po.total_ordered) as total_ordered,
        COALESCE(SUM(r.total_received), 0) as total_received,
        CASE 
          WHEN SUM(po.total_ordered) > 0 
          THEN ROUND((COALESCE(SUM(r.total_received), 0)::numeric / SUM(po.total_ordered)), 3)
          ELSE 0
        END as fulfillment_rate,
        ROUND(SUM(po.total_cost)::numeric, 3) as total_value,
        CASE 
          WHEN COUNT(DISTINCT po.po_id) > 0 
          THEN ROUND(AVG(po.total_cost)::numeric, 3)
          ELSE 0
        END as avg_cost
      FROM po_totals po
      LEFT JOIN receiving_totals r ON po.po_id = r.po_id
    `;

    const { rows: [summary] } = await pool.query(summaryQuery, params);

    // Prepare query based on record type filter to get correct counts
    let countQuery = '';
    
    if (recordType === 'po_only') {
      countQuery = `
        WITH po_data AS (
          SELECT po_id 
          FROM purchase_orders po
          WHERE ${poWhereClause}
          GROUP BY po_id
        ),
        receiving_data AS (
          SELECT receiving_id 
          FROM receivings r
          WHERE ${receivingWhereClause}
          GROUP BY receiving_id
        ),
        filtered_data AS (
          SELECT DISTINCT po_id as id 
          FROM po_data
          WHERE po_id NOT IN (SELECT receiving_id FROM receiving_data WHERE receiving_id IS NOT NULL)
        )
        SELECT COUNT(*) as total FROM filtered_data
      `;
    } else if (recordType === 'po_with_receiving') {
      countQuery = `
        WITH po_data AS (
          SELECT po_id 
          FROM purchase_orders po
          WHERE ${poWhereClause}
          GROUP BY po_id
        ),
        receiving_data AS (
          SELECT receiving_id 
          FROM receivings r
          WHERE ${receivingWhereClause}
          GROUP BY receiving_id
        ),
        filtered_data AS (
          SELECT DISTINCT po_id as id 
          FROM po_data
          WHERE po_id IN (SELECT receiving_id FROM receiving_data WHERE receiving_id IS NOT NULL)
        )
        SELECT COUNT(*) as total FROM filtered_data
      `;
    } else if (recordType === 'receiving_only') {
      countQuery = `
        WITH po_data AS (
          SELECT po_id 
          FROM purchase_orders po
          WHERE ${poWhereClause}
          GROUP BY po_id
        ),
        receiving_data AS (
          SELECT receiving_id 
          FROM receivings r
          WHERE ${receivingWhereClause}
          GROUP BY receiving_id
        ),
        filtered_data AS (
          SELECT DISTINCT receiving_id as id 
          FROM receiving_data
          WHERE receiving_id NOT IN (SELECT po_id FROM po_data WHERE po_id IS NOT NULL)
        )
        SELECT COUNT(*) as total FROM filtered_data
      `;
    } else {
      // 'all' - count both purchase orders and receiving-only records
      countQuery = `
        WITH po_data AS (
          SELECT po_id 
          FROM purchase_orders po
          WHERE ${poWhereClause}
          GROUP BY po_id
        ),
        receiving_data AS (
          SELECT receiving_id 
          FROM receivings r
          WHERE ${receivingWhereClause}
          GROUP BY receiving_id
        ),
        filtered_data AS (
          SELECT DISTINCT po_id as id FROM po_data
          UNION
          SELECT DISTINCT receiving_id as id FROM receiving_data
          WHERE receiving_id NOT IN (SELECT po_id FROM po_data WHERE po_id IS NOT NULL)
        )
        SELECT COUNT(*) as total FROM filtered_data
      `;
    }

    const { rows: [countResult] } = await pool.query(countQuery, params);

    // Parse parameters safely
    const parsedPage = parseInt(page) || 1;
    const parsedLimit = parseInt(limit) || 100;
    const total = parseInt(countResult?.total) || 0;
    const offset = (parsedPage - 1) * parsedLimit;
    const pages = Math.ceil(total / parsedLimit);

    // Validated sort parameters
    const validSortColumns = ['id', 'vendor_name', 'order_date', 'receiving_date', 
      'status', 'total_cost', 'total_items', 'total_quantity', 'total_received', 'fulfillment_rate'];
    
    const finalSortColumn = validSortColumns.includes(sortColumn) ? sortColumn : 'id';
    const finalSortDirection = sortDirection === 'asc' ? 'asc' : 'desc';

    // Build the order by clause with improved null handling
    let orderByClause = '';
    
    // Special sorting that ensures receiving_only records are included with any date sorting
    if (finalSortColumn === 'order_date' || finalSortColumn === 'date') {
      orderByClause = `
        CASE 
          WHEN order_date IS NULL THEN 
            CASE WHEN receiving_date IS NOT NULL THEN 
              to_date(receiving_date, 'YYYY-MM-DD')
            ELSE 
              '1900-01-01'::date
            END
          ELSE 
            to_date(order_date, 'YYYY-MM-DD')
        END ${finalSortDirection === 'desc' ? 'DESC' : 'ASC'}
      `;
    } else if (finalSortColumn === 'receiving_date') {
      orderByClause = `
        CASE WHEN receiving_date IS NULL THEN 
          '1900-01-01'::date
        ELSE 
          to_date(receiving_date, 'YYYY-MM-DD')
        END ${finalSortDirection === 'desc' ? 'DESC' : 'ASC'}
      `;
    } else if (finalSortColumn === 'vendor_name') {
      orderByClause = `vendor_name ${finalSortDirection === 'desc' ? 'DESC NULLS LAST' : 'ASC NULLS FIRST'}`;
    } else if (finalSortColumn === 'total_cost' || finalSortColumn === 'total_received' || 
        finalSortColumn === 'total_items' || finalSortColumn === 'total_quantity' || finalSortColumn === 'fulfillment_rate') {
      orderByClause = `COALESCE(${finalSortColumn}, 0) ${finalSortDirection === 'desc' ? 'DESC' : 'ASC'}`;
    } else if (finalSortColumn === 'status') {
      // For status sorting, first convert to numeric values for consistent sorting
      orderByClause = `
        CASE 
          WHEN status = 'canceled' THEN 0
          WHEN status = 'created' THEN 1
          WHEN status = 'electronically_ready_send' THEN 10
          WHEN status = 'ordered' THEN 11
          WHEN status = 'receiving_started' THEN 15
          WHEN status = 'done' THEN 50
          WHEN status = 'partial_received' THEN 30
          WHEN status = 'full_received' THEN 40
          WHEN status = 'paid' THEN 50
          ELSE 999
        END ${finalSortDirection === 'desc' ? 'DESC' : 'ASC'}
      `;
    } else {
      // Default to ID sorting
      orderByClause = `id::text::bigint ${finalSortDirection === 'desc' ? 'DESC' : 'ASC'}`;
    }

    // Main query to get purchase orders and receivings
    let orderQuery = `
      WITH po_data AS (
        SELECT 
          po_id,
          vendor,
          date,
          status,
          COUNT(DISTINCT pid) as total_items,
          SUM(ordered) as total_quantity,
          ROUND(SUM(ordered * po_cost_price)::numeric, 3) as total_cost,
          MAX(notes) as short_note
        FROM purchase_orders po
        WHERE ${poWhereClause}
        GROUP BY po_id, vendor, date, status
      ),
      receiving_data AS (
        SELECT 
          r.receiving_id,
          MAX(r.received_date) as receiving_date,
          r.vendor as receiving_vendor,
          COUNT(DISTINCT r.pid) as total_items,
          SUM(r.qty_each) as total_received,
          ROUND(SUM(r.qty_each * r.cost_each)::numeric, 3) as total_cost,
          MAX(r.status) as receiving_status
        FROM receivings r
        WHERE ${receivingWhereClause}
        GROUP BY r.receiving_id, r.vendor
      )`;

    // Add appropriate record type filtering based on the filter value
    if (recordType === 'po_only') {
      orderQuery += `,
        all_data AS (
          SELECT DISTINCT po_id as id 
          FROM po_data
          WHERE po_id NOT IN (SELECT receiving_id FROM receiving_data WHERE receiving_id IS NOT NULL)
        )`;
    } else if (recordType === 'po_with_receiving') {
      orderQuery += `,
        all_data AS (
          SELECT DISTINCT po_id as id 
          FROM po_data
          WHERE po_id IN (SELECT receiving_id FROM receiving_data WHERE receiving_id IS NOT NULL)
        )`;
    } else if (recordType === 'receiving_only') {
      orderQuery += `,
        all_data AS (
          SELECT DISTINCT receiving_id as id 
          FROM receiving_data
          WHERE receiving_id NOT IN (SELECT po_id FROM po_data WHERE po_id IS NOT NULL)
        )`;
    } else {
      // 'all' - include all records
      orderQuery += `,
        all_data AS (
          SELECT DISTINCT po_id as id FROM po_data
          UNION
          SELECT DISTINCT receiving_id as id FROM receiving_data
          WHERE receiving_id NOT IN (SELECT po_id FROM po_data WHERE po_id IS NOT NULL)
        )`;
    }

    // Complete the query with combined data and ordering
    orderQuery += `
      ,combined_data AS (
        SELECT
          a.id,
          COALESCE(po.vendor, r.receiving_vendor) as vendor_name,
          to_char(po.date, 'YYYY-MM-DD') as order_date,
          to_char(r.receiving_date, 'YYYY-MM-DD') as receiving_date,
          CASE 
            WHEN po.po_id IS NULL THEN r.receiving_status
            ELSE po.status 
          END as status,
          COALESCE(po.total_items, r.total_items, 0) as total_items,
          COALESCE(po.total_quantity, 0) as total_quantity,
          COALESCE(po.total_cost, r.total_cost, 0) as total_cost,
          COALESCE(r.total_received, 0) as total_received,
          CASE
            WHEN po.po_id IS NULL THEN 1
            WHEN r.receiving_id IS NULL THEN 0
            WHEN po.total_quantity = 0 THEN 0
            ELSE ROUND((r.total_received::numeric / po.total_quantity), 3)
          END as fulfillment_rate,
          po.short_note,
          CASE
            WHEN po.po_id IS NULL THEN 'receiving_only'
            WHEN r.receiving_id IS NULL THEN 'po_only'
            ELSE 'po_with_receiving'
          END as record_type
        FROM all_data a
        LEFT JOIN po_data po ON a.id = po.po_id
        LEFT JOIN receiving_data r ON a.id = r.receiving_id
      )
      SELECT * FROM combined_data
      ORDER BY ${orderByClause}, id::text::bigint DESC
      LIMIT $${paramCounter} OFFSET $${paramCounter + 1}
    `;

    const { rows: orders } = await pool.query(orderQuery, [...params, parsedLimit, offset]);

    // Get unique vendors for filter options
    const { rows: vendors } = await pool.query(`
      SELECT DISTINCT vendor 
      FROM purchase_orders 
      WHERE vendor IS NOT NULL AND vendor != ''
      UNION
      SELECT DISTINCT vendor
      FROM receivings
      WHERE vendor IS NOT NULL AND vendor != ''
      ORDER BY vendor
    `);

    // Get unique statuses for filter options
    const { rows: statuses } = await pool.query(`
      SELECT DISTINCT status 
      FROM purchase_orders 
      WHERE status IS NOT NULL
      UNION
      SELECT DISTINCT status
      FROM receivings
      WHERE status IS NOT NULL
      ORDER BY status
    `);

    // Get product vendors for orders with Unknown Vendor
    const poIds = orders.filter(o => o.vendor_name === 'Unknown Vendor').map(o => o.id);
    let vendorMappings = {};
    
    if (poIds.length > 0) {
      const { rows: productVendors } = await pool.query(`
        SELECT DISTINCT po.po_id, p.vendor 
        FROM purchase_orders po
        JOIN products p ON po.pid = p.pid
        WHERE po.po_id = ANY($1)
        AND p.vendor IS NOT NULL AND p.vendor != ''
        GROUP BY po.po_id, p.vendor
      `, [poIds]);
      
      // Create mapping of PO ID to actual vendor from products table
      vendorMappings = productVendors.reduce((acc, pv) => {
        if (!acc[pv.po_id]) {
          acc[pv.po_id] = pv.vendor;
        }
        return acc;
      }, {});
    }

    // Parse numeric values and map status strings to numeric codes
    const parsedOrders = orders.map(order => {
      // Special handling for status mapping
      let statusCode;
      if (order.record_type === 'receiving_only') {
        // For receiving-only records, use receiving status codes
        statusCode = STATUS_MAPPING[order.status] || 0;
      } else {
        // For PO records, use PO status codes
        statusCode = STATUS_MAPPING[order.status] || 0;
      }

      return {
        id: order.id,
        vendor_name: vendorMappings[order.id] || order.vendor_name,
        order_date: order.order_date,
        receiving_date: order.receiving_date,
        status: statusCode,
        total_items: Number(order.total_items) || 0,
        total_quantity: Number(order.total_quantity) || 0,
        total_cost: Number(order.total_cost) || 0,
        total_received: Number(order.total_received) || 0,
        fulfillment_rate: Number(order.fulfillment_rate) || 0,
        short_note: order.short_note,
        record_type: order.record_type
      };
    });

    // Parse summary metrics with fallbacks
    const parsedSummary = {
      order_count: Number(summary?.order_count) || 0,
      total_ordered: Number(summary?.total_ordered) || 0,
      total_received: Number(summary?.total_received) || 0,
      fulfillment_rate: Number(summary?.fulfillment_rate) || 0,
      total_value: Number(summary?.total_value) || 0,
      avg_cost: Number(summary?.avg_cost) || 0
    };

    console.log(`Returning ${parsedOrders.length} orders, total=${total}, pages=${pages}, page=${parsedPage}`);

    res.json({
      orders: parsedOrders,
      summary: parsedSummary,
      pagination: {
        total,
        pages,
        page: parsedPage,
        limit: parsedLimit
      },
      filters: {
        vendors: vendors.map(v => v.vendor),
        statuses: statuses.map(s => STATUS_MAPPING[s.status] || 0)  // Map string statuses to numeric codes for the frontend
      }
    });
  } catch (error) {
    console.error('Error fetching purchase orders:', error);
    res.status(500).json({ error: 'Failed to fetch purchase orders', details: error.message });
  }
});

// Get vendor performance metrics
router.get('/vendor-metrics', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    const { rows: metrics } = await pool.query(`
      WITH po_data AS (
        SELECT 
          vendor,
          po_id,
          SUM(ordered) as total_ordered,
          AVG(po_cost_price) as avg_cost_price,
          MAX(date) as po_date
        FROM purchase_orders
        WHERE vendor IS NOT NULL AND vendor != ''
          AND status != 'canceled'  -- Exclude canceled orders
        GROUP BY vendor, po_id
      ),
      receiving_data AS (
        SELECT 
          r.receiving_id as po_id,
          SUM(r.qty_each) as total_received,
          MIN(r.received_date) as first_received_date
        FROM receivings r
        JOIN purchase_orders po ON r.receiving_id = po.po_id
        WHERE po.vendor IS NOT NULL AND po.vendor != ''
          AND po.status != 'canceled'
        GROUP BY r.receiving_id
      ),
      delivery_metrics AS (
        SELECT 
          po.vendor,
          po.po_id,
          po.total_ordered as ordered,
          COALESCE(r.total_received, 0) as received,
          po.avg_cost_price as po_cost_price,
          CASE 
            WHEN r.first_received_date IS NOT NULL AND po.po_date IS NOT NULL
            THEN EXTRACT(DAY FROM (r.first_received_date - po.po_date))
            ELSE NULL
          END as delivery_days
        FROM po_data po
        LEFT JOIN receiving_data r ON po.po_id = r.po_id
      )
      SELECT 
        vendor as vendor_name,
        COUNT(DISTINCT po_id) as total_orders,
        SUM(ordered) as total_ordered,
        SUM(received) as total_received,
        ROUND(
          (SUM(received)::numeric / NULLIF(SUM(ordered), 0)), 3
        ) as fulfillment_rate,
        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,
        ROUND(
          AVG(NULLIF(delivery_days, 0))::numeric, 1
        ) as avg_delivery_days
      FROM delivery_metrics
      GROUP BY vendor
      HAVING COUNT(DISTINCT po_id) > 0
      ORDER BY total_spend DESC
    `);

    // Parse numeric values
    const parsedMetrics = metrics.map(vendor => ({
      id: vendor.vendor_name,
      vendor_name: vendor.vendor_name,
      total_orders: Number(vendor.total_orders) || 0,
      total_ordered: Number(vendor.total_ordered) || 0,
      total_received: Number(vendor.total_received) || 0,
      fulfillment_rate: Number(vendor.fulfillment_rate) || 0,
      avg_unit_cost: Number(vendor.avg_unit_cost) || 0,
      total_spend: Number(vendor.total_spend) || 0,
      avg_delivery_days: Number(vendor.avg_delivery_days) || 0
    }));

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

// Get cost analysis
router.get('/cost-analysis', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    const { rows: analysis } = await pool.query(`
      WITH category_costs AS (
        SELECT 
          c.name as category,
          po.pid,
          po.po_cost_price as cost_price,
          po.ordered,
          po.status
        FROM purchase_orders po
        JOIN product_categories pc ON po.pid = pc.pid
        JOIN categories c ON pc.cat_id = c.cat_id
        WHERE po.status != 'canceled'  -- Exclude canceled orders
      )
      SELECT 
        category,
        COUNT(DISTINCT pid) as unique_products,
        ROUND(AVG(cost_price)::numeric, 3) as avg_cost,
        ROUND(MIN(cost_price)::numeric, 3) as min_cost,
        ROUND(MAX(cost_price)::numeric, 3) as max_cost,
        ROUND(STDDEV(cost_price)::numeric, 3) as cost_variance,
        ROUND(SUM(ordered * cost_price)::numeric, 3) as total_spend
      FROM category_costs
      GROUP BY category
      ORDER BY total_spend DESC
    `);

    // Parse numeric values and include ALL data for each category
    const parsedAnalysis = {
      unique_products: 0,
      avg_cost: 0,
      min_cost: 0,
      max_cost: 0,
      cost_variance: 0,
      total_spend_by_category: analysis.map(cat => ({
        category: cat.category,
        unique_products: Number(cat.unique_products) || 0,
        avg_cost: Number(cat.avg_cost) || 0,
        min_cost: Number(cat.min_cost) || 0,
        max_cost: Number(cat.max_cost) || 0,
        cost_variance: Number(cat.cost_variance) || 0,
        total_spend: Number(cat.total_spend) || 0
      }))
    };

    // Calculate aggregated stats if data exists
    if (analysis.length > 0) {
      parsedAnalysis.unique_products = analysis.reduce((sum, cat) => sum + Number(cat.unique_products || 0), 0);
      
      // Calculate weighted average cost
      const totalProducts = parsedAnalysis.unique_products;
      if (totalProducts > 0) {
        parsedAnalysis.avg_cost = analysis.reduce((sum, cat) => 
          sum + (Number(cat.avg_cost || 0) * Number(cat.unique_products || 0)), 0) / totalProducts;
      }
      
      // Find min and max across all categories
      parsedAnalysis.min_cost = Math.min(...analysis.map(cat => Number(cat.min_cost || 0)));
      parsedAnalysis.max_cost = Math.max(...analysis.map(cat => Number(cat.max_cost || 0)));
      
      // Average variance
      parsedAnalysis.cost_variance = analysis.reduce((sum, cat) => 
        sum + Number(cat.cost_variance || 0), 0) / analysis.length;
    }

    res.json(parsedAnalysis);
  } catch (error) {
    console.error('Error fetching cost analysis:', error);
    res.status(500).json({ error: 'Failed to fetch cost analysis' });
  }
});

// New endpoint for yearly category spending analysis based on receivings
router.get('/category-analysis', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    // Allow an optional "since" parameter or default to 1 year ago
    const since = req.query.since || businessNow().minus({ days: 365 }).toISODate();
    
    const { rows: analysis } = await pool.query(`
      WITH receiving_costs AS (
        SELECT 
          c.name as category,
          r.pid,
          r.cost_each as received_cost,
          r.qty_each as received_qty,
          r.received_date
        FROM receivings r
        JOIN product_categories pc ON r.pid = pc.pid
        JOIN categories c ON pc.cat_id = c.cat_id
        WHERE r.received_date >= $1::date
          AND r.qty_each > 0  -- Only consider actual received quantities
      )
      SELECT 
        category,
        COUNT(DISTINCT pid) as unique_products,
        ROUND(AVG(received_cost)::numeric, 3) as avg_cost,
        ROUND(MIN(received_cost)::numeric, 3) as min_cost,
        ROUND(MAX(received_cost)::numeric, 3) as max_cost,
        ROUND(STDDEV(received_cost)::numeric, 3) as cost_variance,
        ROUND(SUM(received_qty * received_cost)::numeric, 3) as total_spend
      FROM receiving_costs
      GROUP BY category
      ORDER BY total_spend DESC
    `, [since]);

    // Parse numeric values
    const parsedAnalysis = analysis.map(cat => ({
      category: cat.category,
      unique_products: Number(cat.unique_products) || 0,
      avg_cost: Number(cat.avg_cost) || 0,
      min_cost: Number(cat.min_cost) || 0,
      max_cost: Number(cat.max_cost) || 0,
      cost_variance: Number(cat.cost_variance) || 0,
      total_spend: Number(cat.total_spend) || 0
    }));

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

// New endpoint for yearly vendor spending analysis based on receivings
router.get('/vendor-analysis', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    // Allow an optional "since" parameter or default to 1 year ago
    const since = req.query.since || businessNow().minus({ days: 365 }).toISODate();
    
    const { rows: metrics } = await pool.query(`
      WITH receiving_data AS (
        SELECT 
          r.vendor,
          r.receiving_id,
          r.pid,
          r.qty_each,
          r.cost_each,
          r.received_date
        FROM receivings r
        WHERE r.received_date >= $1::date
          AND r.qty_each > 0  -- Only consider actual received quantities
      ),
      receiving_totals AS (
        SELECT 
          vendor,
          receiving_id,
          COUNT(DISTINCT pid) as unique_products,
          SUM(qty_each) as total_received,
          SUM(qty_each * cost_each) as total_spend
        FROM receiving_data
        GROUP BY vendor, receiving_id
      )
      SELECT 
        vendor,
        COUNT(DISTINCT receiving_id) as orders,
        ROUND(SUM(total_spend)::numeric, 3) as total_spend,
        SUM(total_received) as total_received,
        SUM(unique_products) as total_items
      FROM receiving_totals
      WHERE vendor IS NOT NULL AND vendor != ''
      GROUP BY vendor
      HAVING COUNT(DISTINCT receiving_id) > 0
      ORDER BY total_spend DESC
    `, [since]);

    // Parse numeric values
    const parsedMetrics = metrics.map(vendor => ({
      vendor: vendor.vendor,
      orders: Number(vendor.orders) || 0,
      total_spend: Number(vendor.total_spend) || 0,
      total_received: Number(vendor.total_received) || 0,
      total_items: Number(vendor.total_items) || 0
    }));

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

// Get order status metrics
router.get('/receiving-status', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    const { rows: status } = await pool.query(`
      WITH po_totals AS (
        SELECT 
          po_id,
          status,
          SUM(ordered) as total_ordered,
          ROUND(SUM(ordered * po_cost_price)::numeric, 3) as total_cost
        FROM purchase_orders
        WHERE status != 'canceled'
        GROUP BY po_id, status
      ),
      receiving_totals AS (
        SELECT 
          po.po_id,
          SUM(r.qty_each) as total_received
        FROM receivings r
        JOIN purchase_orders po ON r.pid = po.pid AND r.sku = po.sku
        WHERE po.po_id IN (SELECT po_id FROM po_totals)
        GROUP BY po.po_id
      ),
      combined_data AS (
        SELECT 
          po.po_id,
          po.status,
          po.total_ordered,
          po.total_cost,
          COALESCE(r.total_received, 0) as total_received
        FROM po_totals po
        LEFT JOIN receiving_totals r ON po.po_id = r.po_id
      )
      SELECT 
        COUNT(DISTINCT po_id) as order_count,
        SUM(total_ordered) as total_ordered,
        SUM(total_received) as total_received,
        ROUND(
          SUM(total_received) / NULLIF(SUM(total_ordered), 0), 3
        ) as fulfillment_rate,
        ROUND(SUM(total_cost)::numeric, 3) as total_value,
        ROUND(AVG(total_cost)::numeric, 3) as avg_cost,
        COUNT(DISTINCT CASE 
          WHEN status = 'created' THEN po_id 
          END) as pending_count,
        COUNT(DISTINCT CASE 
          WHEN status = 'receiving_started' THEN po_id 
          END) as partial_count,
        COUNT(DISTINCT CASE 
          WHEN status = 'done' THEN po_id 
          END) as completed_count,
        COUNT(DISTINCT CASE 
          WHEN status = 'canceled' THEN po_id 
          END) as canceled_count
      FROM combined_data
    `);

    // Parse numeric values
    const parsedStatus = {
      order_count: Number(status[0]?.order_count) || 0,
      total_ordered: Number(status[0]?.total_ordered) || 0,
      total_received: Number(status[0]?.total_received) || 0,
      fulfillment_rate: Number(status[0]?.fulfillment_rate) || 0,
      total_value: Number(status[0]?.total_value) || 0,
      avg_cost: Number(status[0]?.avg_cost) || 0,
      status_breakdown: {
        pending: Number(status[0]?.pending_count) || 0,
        partial: Number(status[0]?.partial_count) || 0,
        completed: Number(status[0]?.completed_count) || 0,
        canceled: Number(status[0]?.canceled_count) || 0
      }
    };

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

// Get order vs received quantities by product
router.get('/order-vs-received', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    const { rows: quantities } = await pool.query(`
      WITH order_data AS (
        SELECT 
          p.pid,
          p.title,
          p.SKU,
          SUM(po.ordered) as ordered_quantity,
          COUNT(DISTINCT po.po_id) as order_count
        FROM products p
        JOIN purchase_orders po ON p.pid = po.pid
        WHERE po.date >= (CURRENT_DATE - INTERVAL '90 days')
        GROUP BY p.pid, p.title, p.SKU
      ),
      receiving_data AS (
        SELECT 
          r.pid,
          SUM(r.qty_each) as received_quantity
        FROM receivings r
        JOIN purchase_orders po ON r.receiving_id = po.po_id
        WHERE r.received_date >= (CURRENT_DATE - INTERVAL '90 days')
        GROUP BY r.pid
      )
      SELECT 
        o.pid as product_id,
        o.title as product,
        o.SKU as sku,
        o.ordered_quantity,
        COALESCE(r.received_quantity, 0) as received_quantity,
        ROUND(
          COALESCE(r.received_quantity, 0) / NULLIF(o.ordered_quantity, 0) * 100, 1
        ) as fulfillment_rate,
        o.order_count
      FROM order_data o
      LEFT JOIN receiving_data r ON o.pid = r.pid
      WHERE o.order_count > 0
      ORDER BY o.ordered_quantity DESC
      LIMIT 20
    `);

    // Parse numeric values and add id for React keys
    const parsedQuantities = quantities.map(q => ({
      id: q.product_id,
      ...q,
      ordered_quantity: Number(q.ordered_quantity) || 0,
      received_quantity: Number(q.received_quantity) || 0,
      fulfillment_rate: Number(q.fulfillment_rate) || 0,
      order_count: Number(q.order_count) || 0
    }));

    res.json(parsedQuantities);
  } catch (error) {
    console.error('Error fetching order vs received quantities:', error);
    res.status(500).json({ error: 'Failed to fetch order vs received quantities' });
  }
});

// Get purchase order items
// Lightweight lookup of a PO's supplier_id by po_id, used by the Create-PO
// page's "Add to existing PO" mode so we can compute the right cost-each
// fallback branch (Notions supplier 92 vs everyone else) without fetching
// the full PO contents.
router.get('/:id/supplier', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    const { id } = req.params;
    if (!id) {
      return res.status(400).json({ error: 'Purchase order ID is required' });
    }
    const { rows } = await pool.query(
      `SELECT supplier_id, vendor FROM purchase_orders WHERE po_id = $1 LIMIT 1`,
      [String(id)]
    );
    if (rows.length === 0) {
      return res.status(404).json({ error: 'Purchase order not found' });
    }
    res.json({
      supplierId: rows[0].supplier_id != null ? Number(rows[0].supplier_id) : null,
      vendor: rows[0].vendor || null,
    });
  } catch (error) {
    console.error('Error fetching PO supplier:', error);
    res.status(500).json({ error: 'Failed to fetch PO supplier' });
  }
});

router.get('/:id/items', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    const { id } = req.params;
    
    if (!id) {
      return res.status(400).json({ error: 'Purchase order ID is required' });
    }
    
    // Query to get purchase order items with product details
    const { rows: items } = await pool.query(`
      WITH po_items AS (
        SELECT 
          po.po_id,
          po.pid,
          po.sku,
          COALESCE(po.name, p.title) as product_name,
          po.po_cost_price,
          po.ordered,
          po.status
        FROM purchase_orders po
        LEFT JOIN products p ON po.pid = p.pid
        WHERE po.po_id = $1
      ),
      receiving_items AS (
        SELECT 
          r.receiving_id,
          r.pid,
          r.sku,
          SUM(r.qty_each) as received
        FROM receivings r
        WHERE r.receiving_id = $1
        GROUP BY r.receiving_id, r.pid, r.sku
      )
      SELECT 
        pi.po_id as id,
        pi.pid,
        pi.sku,
        pi.product_name,
        p.barcode,
        pi.po_cost_price,
        pi.ordered,
        COALESCE(ri.received, 0) as received,
        ROUND(pi.ordered * pi.po_cost_price, 2) as total_cost,
        CASE
          WHEN ri.received IS NULL THEN 'Not Received'
          WHEN ri.received = 0 THEN 'Not Received'
          WHEN ri.received < pi.ordered THEN 'Partially Received'
          WHEN ri.received >= pi.ordered THEN 'Fully Received'
        END as receiving_status
      FROM po_items pi
      LEFT JOIN receiving_items ri ON pi.pid = ri.pid AND pi.sku = ri.sku
      LEFT JOIN products p ON pi.pid = p.pid
      ORDER BY pi.product_name
    `, [id]);
    
    // Parse numeric values
    const parsedItems = items.map(item => ({
      id: `${item.id}_${item.pid}`,
      pid: item.pid,
      product_name: item.product_name,
      sku: item.sku,
      upc: item.barcode || 'N/A',
      ordered: Number(item.ordered) || 0,
      received: Number(item.received) || 0,
      po_cost_price: Number(item.po_cost_price) || 0,
      total_cost: Number(item.total_cost) || 0,
      receiving_status: item.receiving_status
    }));
    
    res.json(parsedItems);
  } catch (error) {
    console.error('Error fetching purchase order items:', error);
    res.status(500).json({ error: 'Failed to fetch purchase order items', details: error.message });
  }
});

// Get receiving items
router.get('/receiving/:id/items', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    const { id } = req.params;
    
    if (!id) {
      return res.status(400).json({ error: 'Receiving ID is required' });
    }
    
    // Query to get receiving items with related PO information if available
    const { rows: items } = await pool.query(`
      WITH receiving_items AS (
        SELECT 
          r.receiving_id,
          r.pid,
          r.sku,
          COALESCE(r.name, p.title) as product_name,
          r.cost_each,
          r.qty_each,
          r.status
        FROM receivings r
        LEFT JOIN products p ON r.pid = p.pid
        WHERE r.receiving_id = $1
      ),
      po_items AS (
        SELECT 
          po.po_id,
          po.pid,
          po.sku,
          po.ordered,
          po.po_cost_price
        FROM purchase_orders po
        WHERE po.po_id = $1
      )
      SELECT 
        ri.receiving_id as id,
        ri.pid,
        ri.sku,
        ri.product_name,
        p.barcode,
        COALESCE(po.ordered, 0) as ordered,
        ri.qty_each as received,
        COALESCE(po.po_cost_price, ri.cost_each) as po_cost_price,
        ri.cost_each,
        ROUND(ri.qty_each * ri.cost_each, 2) as total_cost,
        CASE
          WHEN po.ordered IS NULL THEN 'Receiving Only'
          WHEN ri.qty_each < po.ordered THEN 'Partially Received'
          WHEN ri.qty_each >= po.ordered THEN 'Fully Received'
        END as receiving_status
      FROM receiving_items ri
      LEFT JOIN po_items po ON ri.pid = po.pid AND ri.sku = po.sku
      LEFT JOIN products p ON ri.pid = p.pid
      ORDER BY ri.product_name
    `, [id]);
    
    // Parse numeric values
    const parsedItems = items.map(item => ({
      id: `${item.id}_${item.pid}`,
      pid: item.pid,
      product_name: item.product_name,
      sku: item.sku,
      upc: item.barcode || 'N/A',
      ordered: Number(item.ordered) || 0,
      received: Number(item.received) || 0,
      po_cost_price: Number(item.po_cost_price) || 0,
      cost_each: Number(item.cost_each) || 0,
      qty_each: Number(item.received) || 0,
      total_cost: Number(item.total_cost) || 0,
      receiving_status: item.receiving_status
    }));
    
    res.json(parsedItems);
  } catch (error) {
    console.error('Error fetching receiving items:', error);
    res.status(500).json({ error: 'Failed to fetch receiving items', details: error.message });
  }
});

// New endpoint for delivery metrics
router.get('/delivery-metrics', async (req, res) => {
  try {
    const pool = req.app.locals.pool;
    
    const { rows: deliveryData } = await pool.query(`
      WITH po_dates AS (
        SELECT 
          po_id,
          date as order_date
        FROM purchase_orders 
        WHERE status != 'canceled'
        GROUP BY po_id, date
      ),
      receiving_dates AS (
        SELECT 
          receiving_id as po_id,
          MIN(received_date) as first_received_date
        FROM receivings
        GROUP BY receiving_id
      ),
      delivery_times AS (
        SELECT 
          po.po_id,
          po.order_date,
          r.first_received_date,
          CASE 
            WHEN r.first_received_date IS NOT NULL AND po.order_date IS NOT NULL
            THEN (r.first_received_date::date - po.order_date::date)
            ELSE NULL
          END as delivery_days
        FROM po_dates po
        JOIN receiving_dates r ON po.po_id = r.po_id
        WHERE 
          r.first_received_date IS NOT NULL 
          AND po.order_date IS NOT NULL
          AND r.first_received_date::date >= po.order_date::date
      )
      SELECT 
        ROUND(AVG(delivery_days)::numeric, 1) as avg_delivery_days,
        ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY delivery_days)::numeric, 1) as median_delivery_days,
        MIN(delivery_days) as min_delivery_days,
        MAX(delivery_days) as max_delivery_days,
        COUNT(*) as total_orders_with_delivery
      FROM delivery_times
      WHERE delivery_days >= 0 AND delivery_days <= 365  -- Filter out unreasonable values
    `);

    res.json({
      avg_delivery_days: Number(deliveryData[0]?.avg_delivery_days) || 0,
      median_delivery_days: Number(deliveryData[0]?.median_delivery_days) || 0,
      min_delivery_days: Number(deliveryData[0]?.min_delivery_days) || 0,
      max_delivery_days: Number(deliveryData[0]?.max_delivery_days) || 0,
      total_orders_with_delivery: Number(deliveryData[0]?.total_orders_with_delivery) || 0
    });
  } catch (error) {
    console.error('Error fetching delivery metrics:', error);
    res.status(500).json({ error: 'Failed to fetch delivery metrics' });
  }
});

// PO Pipeline — expected arrivals timeline + overdue summary
router.get('/pipeline', async (req, res) => {
  try {
    const pool = req.app.locals.pool;

    // Stale PO filter (reused across queries)
    const staleFilter = `
      WITH stale AS (
          SELECT po_id, pid
          FROM purchase_orders po
          WHERE po.status IN ('created', 'ordered', 'preordered', 'electronically_sent',
                              'electronically_ready_send', 'receiving_started')
            AND po.expected_date IS NOT NULL
            AND po.expected_date < CURRENT_DATE - INTERVAL '90 days'
            AND EXISTS (
                SELECT 1 FROM purchase_orders newer
                WHERE newer.pid = po.pid
                  AND newer.status NOT IN ('canceled', 'done')
                  AND COALESCE(newer.date_ordered, newer.date_created)
                      > COALESCE(po.date_ordered, po.date_created)
            )
      )`;

    // Expected arrivals by week (excludes stale POs)
    const { rows: arrivals } = await pool.query(`
      ${staleFilter}
      SELECT
        DATE_TRUNC('week', po.expected_date)::date AS week,
        COUNT(DISTINCT po.po_id) AS po_count,
        ROUND(SUM(po.po_cost_price * po.ordered)::numeric, 0) AS expected_value,
        COUNT(DISTINCT po.vendor) AS vendor_count
      FROM purchase_orders po
      WHERE po.status IN ('ordered', 'electronically_sent')
        AND po.expected_date IS NOT NULL
        AND NOT EXISTS (SELECT 1 FROM stale s WHERE s.po_id = po.po_id AND s.pid = po.pid)
      GROUP BY 1
      ORDER BY 1
    `);

    // Overdue POs (excludes stale)
    const { rows: [overdue] } = await pool.query(`
      ${staleFilter}
      SELECT
        COUNT(DISTINCT po.po_id) AS po_count,
        ROUND(COALESCE(SUM(po.po_cost_price * po.ordered), 0)::numeric, 0) AS total_value
      FROM purchase_orders po
      WHERE po.status IN ('ordered', 'electronically_sent')
        AND po.expected_date IS NOT NULL
        AND po.expected_date < CURRENT_DATE
        AND NOT EXISTS (SELECT 1 FROM stale s WHERE s.po_id = po.po_id AND s.pid = po.pid)
    `);

    // Summary: on-order value from product_metrics (FIFO-accurate), PO counts from purchase_orders with staleness filter
    const { rows: [summary] } = await pool.query(`
      ${staleFilter}
      SELECT
        COUNT(DISTINCT po.po_id) AS total_open_pos,
        COUNT(DISTINCT po.vendor) AS vendor_count
      FROM purchase_orders po
      WHERE po.status IN ('ordered', 'electronically_sent')
        AND NOT EXISTS (SELECT 1 FROM stale s WHERE s.po_id = po.po_id AND s.pid = po.pid)
    `);

    const { rows: [onOrderTotal] } = await pool.query(`
      SELECT ROUND(COALESCE(SUM(on_order_cost), 0)::numeric, 0) AS total_on_order_value
      FROM product_metrics
      WHERE is_visible = true
    `);

    res.json({
      arrivals: arrivals.map(r => ({
        week: r.week,
        poCount: Number(r.po_count) || 0,
        expectedValue: Number(r.expected_value) || 0,
        vendorCount: Number(r.vendor_count) || 0,
      })),
      overdue: {
        count: Number(overdue.po_count) || 0,
        value: Number(overdue.total_value) || 0,
      },
      summary: {
        totalOpenPOs: Number(summary.total_open_pos) || 0,
        totalOnOrderValue: Number(onOrderTotal.total_on_order_value) || 0,
        vendorCount: Number(summary.vendor_count) || 0,
      },
    });
  } catch (error) {
    console.error('Error fetching PO pipeline:', error);
    res.status(500).json({ error: 'Failed to fetch PO pipeline' });
  }
});

export default router;